199 lines
4.5 KiB
Vue
199 lines
4.5 KiB
Vue
<template>
|
|
<section class="hero">
|
|
<SMLoading v-if="!loaded" large />
|
|
<template v-else>
|
|
<div class="hero-background" :style="heroStyles"></div>
|
|
<SMContainer class="hero-container">
|
|
<div class="hero-content">
|
|
<h1>{{ props.title }}</h1>
|
|
<p>{{ props.excerpt }}</p>
|
|
<div class="hero-buttons">
|
|
<SMButton
|
|
v-if="loaded"
|
|
type="primary"
|
|
:to="props.to"
|
|
:label="props.more" />
|
|
</div>
|
|
</div>
|
|
</SMContainer>
|
|
<div class="hero-caption">
|
|
<router-link v-if="loaded" :to="props.to">{{
|
|
props.imageTitle
|
|
}}</router-link>
|
|
</div>
|
|
</template>
|
|
</section>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed, onBeforeUnmount, onMounted, ref, watch } from "vue";
|
|
import { api, getApiResultData } from "../helpers/api";
|
|
import { ArticleCollection } from "../helpers/api.types";
|
|
import { mediaGetVariantUrl } from "../helpers/media";
|
|
import { excerpt } from "../helpers/string";
|
|
import SMButton from "./SMButton.vue";
|
|
import SMLoading from "./SMLoading.vue";
|
|
|
|
const props = defineProps({
|
|
title: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
excerpt: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
imageUrl: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
imageTitle: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
to: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
more: {
|
|
type: String,
|
|
default: "Read More",
|
|
required: false,
|
|
},
|
|
});
|
|
|
|
const loaded = ref(false);
|
|
const translateY = ref(0);
|
|
const heroStyles = ref({
|
|
backgroundImage: "none",
|
|
transform: "translateY(0px)",
|
|
});
|
|
|
|
const handleScroll = () => {
|
|
const scrollTop = window.scrollY;
|
|
translateY.value = scrollTop / 2.5;
|
|
};
|
|
|
|
watch(translateY, () => {
|
|
heroStyles.value.transform = `translateY(${translateY.value}px)`;
|
|
});
|
|
|
|
const updateImageUrl = (url: string) => {
|
|
heroStyles.value.backgroundImage = `linear-gradient(to right, rgba(0, 0, 0, 0.7),rgba(0, 0, 0, 0.2)),url('${url}')`;
|
|
loaded.value = true;
|
|
};
|
|
|
|
watch(
|
|
() => props.imageUrl,
|
|
() => {
|
|
updateImageUrl(props.imageUrl);
|
|
}
|
|
);
|
|
|
|
onMounted(() => {
|
|
window.addEventListener("scroll", handleScroll);
|
|
});
|
|
|
|
onBeforeUnmount(() => {
|
|
window.removeEventListener("scroll", handleScroll);
|
|
});
|
|
|
|
if (props.imageUrl && props.imageUrl !== "") {
|
|
updateImageUrl(props.imageUrl);
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.hero {
|
|
display: flex;
|
|
position: relative;
|
|
overflow: hidden;
|
|
min-height: 101vh;
|
|
|
|
.hero-background {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background-position: center;
|
|
background-repeat: no-repeat;
|
|
background-size: cover;
|
|
}
|
|
|
|
.hero-container {
|
|
align-items: flex-start;
|
|
}
|
|
|
|
.hero-content {
|
|
position: relative;
|
|
margin: 150px 32px 120px;
|
|
max-width: 640px;
|
|
|
|
h1 {
|
|
font-size: 300%;
|
|
margin-bottom: 20px;
|
|
max-width: 550px;
|
|
color: var(--hero-color-text);
|
|
text-align: left;
|
|
text-shadow: var(--hero-shadow);
|
|
}
|
|
|
|
p {
|
|
max-width: 550px;
|
|
color: var(--hero-color-text);
|
|
text-align: left;
|
|
text-shadow: var(--hero-shadow);
|
|
}
|
|
}
|
|
|
|
.hero-caption {
|
|
position: absolute;
|
|
bottom: 14px;
|
|
right: 30px;
|
|
color: var(--hero-caption-color-text);
|
|
font-size: 80%;
|
|
padding: 6px 12px;
|
|
background-color: var(--hero-caption-color);
|
|
|
|
a {
|
|
color: inherit;
|
|
transition: color 0.1s ease-in-out;
|
|
text-decoration: none;
|
|
|
|
&:hover {
|
|
text-decoration: none;
|
|
color: var(--hero-caption-color-link);
|
|
}
|
|
}
|
|
}
|
|
|
|
.hero-buttons {
|
|
padding-top: 48px;
|
|
|
|
.primary {
|
|
background-color: var(--primary-color-dark);
|
|
}
|
|
}
|
|
}
|
|
|
|
@media only screen and (max-width: 640px) {
|
|
.hero {
|
|
.hero-container {
|
|
align-items: center;
|
|
}
|
|
|
|
.hero-content {
|
|
margin: 150px 0;
|
|
}
|
|
|
|
.hero-buttons {
|
|
.button {
|
|
display: block;
|
|
text-align: center;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|