working on start page
This commit is contained in:
@@ -1,55 +1,62 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="js">
|
||||||
import { onMounted, ref } from "vue"
|
import { onMounted, onUnmounted, ref } from "vue"
|
||||||
import gsap from "gsap"
|
import gsap from "gsap"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const box = ref<HTMLElement | null>(null)
|
const main = ref(null);
|
||||||
|
let tl;
|
||||||
|
let ctx;
|
||||||
|
|
||||||
const heroText = ref<HTMLElement | null>(null)
|
function toggleTimeline() {
|
||||||
const c = ref<HTMLElement | null>(null)
|
tl.reversed(!tl.reversed())
|
||||||
//section.value = document.querySelector(".hero")
|
}
|
||||||
|
function startNextAnimation() {
|
||||||
|
ctx = gsap.context((self) => {
|
||||||
|
const boxes = gsap.utils.toArray('.box')
|
||||||
|
tl = gsap.timeline({delay:2})
|
||||||
|
.to(boxes[0], {x: gsap.utils.random(300, 600), rotate :180})
|
||||||
|
.to(boxes[1], {x:-gsap.utils.random(300, 500), rotate: -180}, '<')
|
||||||
|
.to(boxes[2], {x: gsap.utils.random(300, 400) , rotate: 180})
|
||||||
|
.to(boxes[3], {x: gsap.utils.random(300, 500), rotate : 180})
|
||||||
|
.to(boxes[4], {x: - gsap.utils.random(300, 400), rotate: -180}, '<')
|
||||||
|
.to(boxes[5], {x: gsap.utils.random(300, 500) , rotate: 180})
|
||||||
|
.to(boxes[6], {x: - gsap.utils.random(300, 600), rotate: 180})
|
||||||
|
.to(".title", {
|
||||||
|
y: window.innerHeight - 130,
|
||||||
|
duration: 1.2,
|
||||||
|
ease: "power2.inOut"
|
||||||
|
})
|
||||||
|
.reverse();
|
||||||
|
}, main.value);
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (box.value) {
|
startNextAnimation();
|
||||||
gsap.fromTo(box.value, { yPercent: 100 , delay : 1 }, { x: () => window.innerWidth * 0.4 , y: () => window.innerHeight * 0.1 ,rotate: 90, duration: 4, repeat: 8, yoyo: true, delay : 1})
|
tl.reversed(false);
|
||||||
}
|
});
|
||||||
if (heroText.value) {
|
|
||||||
gsap.fromTo(
|
|
||||||
heroText.value,
|
|
||||||
{
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
|
|
||||||
},
|
onUnmounted(() => {
|
||||||
{
|
ctx.revert()
|
||||||
// x: () => window.innerWidth / 2 - heroText.value!.offsetWidth / 2,
|
|
||||||
y: () => window.innerHeight / 2 - heroText.value!.offsetHeight / 2 + 25,
|
|
||||||
duration: 4,
|
|
||||||
ease: "power2.inOut"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (c.value) {
|
|
||||||
gsap.fromTo(c.value, {delay: 1}, {
|
|
||||||
x: () => window.innerWidth * 0.1,
|
|
||||||
y: () => window.innerHeight * 0.1,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="container">
|
<section class="container" ref="main">
|
||||||
<div ref="box" class="box green"></div>
|
<h1 class="title">Welcome</h1>
|
||||||
<section ref="section" class="hero">
|
<div>
|
||||||
<div ref="heroText" class="hero-text">
|
|
||||||
<div class="titel" >Welcome</div>
|
|
||||||
<div>to my website</div>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- <p class="hero-sub">Tom Herpel</p> -->
|
<div class="box"></div>
|
||||||
|
<div class="box"></div>
|
||||||
|
<div class="box"></div>
|
||||||
|
<div class="box"></div>
|
||||||
|
<div class="box"></div>
|
||||||
|
<div class="box"></div>
|
||||||
|
<div class="box"></div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@@ -60,10 +67,6 @@ onMounted(() => {
|
|||||||
rgb(0, 0, 0) 90%
|
rgb(0, 0, 0) 90%
|
||||||
);
|
);
|
||||||
background-blend-mode: color-dodge;
|
background-blend-mode: color-dodge;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.hero {
|
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
color: white;
|
color: white;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -71,7 +74,9 @@ onMounted(() => {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
.hero-text {
|
|
||||||
|
|
||||||
|
.title {
|
||||||
font-display: block;
|
font-display: block;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@@ -80,7 +85,10 @@ onMounted(() => {
|
|||||||
|
|
||||||
font-size: clamp(2rem, 12rem, 5vw);
|
font-size: clamp(2rem, 12rem, 5vw);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
width: 100%;
|
font-display: block;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
}
|
}
|
||||||
.titel {
|
.titel {
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
import gsap from "gsap"
|
|
||||||
import ScrollTrigger from "gsap/ScrollTrigger"
|
|
||||||
|
|
||||||
gsap.registerPlugin(ScrollTrigger)
|
|
||||||
|
|
||||||
export { gsap, ScrollTrigger }
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
import { onMounted, onUnmounted, ref } from 'vue'
|
|
||||||
import gsap from 'gsap'
|
|
||||||
import ScrollTrigger from 'gsap/ScrollTrigger'
|
|
||||||
// import { useSectionStore } from '../store/useActiveSection'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gsap.registerPlugin(ScrollTrigger)
|
|
||||||
|
|
||||||
export function useActiveSection(sectionIds: string[]) {
|
|
||||||
//const uiStore = useSectionStore();
|
|
||||||
const currentSection = ref<string | null>(null)
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
sectionIds.forEach(id => {
|
|
||||||
const el = document.getElementById(id)
|
|
||||||
if (!el) return
|
|
||||||
|
|
||||||
ScrollTrigger.create({
|
|
||||||
trigger: el,
|
|
||||||
start: 'top center',
|
|
||||||
end: 'bottom center',
|
|
||||||
onEnter: () => {
|
|
||||||
if (currentSection.value !== id) {
|
|
||||||
currentSection.value = id
|
|
||||||
|
|
||||||
console.log(`Section aktiv: ${id} (nach unten gescrollt)`);
|
|
||||||
window.dispatchEvent(new CustomEvent('section:enter', {detail: id}))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onEnterBack: () => {
|
|
||||||
if (currentSection.value !== id) {
|
|
||||||
currentSection.value = id
|
|
||||||
window.dispatchEvent(new CustomEvent('section:enter', {detail : id}))
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
ScrollTrigger.getAll().forEach(t => t.kill())
|
|
||||||
})
|
|
||||||
|
|
||||||
return { currentSection }
|
|
||||||
}
|
|
||||||
@@ -2,9 +2,7 @@
|
|||||||
import HeroSection from '../components/sections/HeroSection.vue'
|
import HeroSection from '../components/sections/HeroSection.vue'
|
||||||
import ImageSection from '../components/sections/ImageSection.vue'
|
import ImageSection from '../components/sections/ImageSection.vue'
|
||||||
import TextSection from '../components/sections/TextSection.vue'
|
import TextSection from '../components/sections/TextSection.vue'
|
||||||
import { useActiveSection } from '../composables/useScrollAnimations'
|
|
||||||
|
|
||||||
const { currentSection } = useActiveSection(['hero', 'image', 'text'])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -14,10 +12,6 @@ const { currentSection } = useActiveSection(['hero', 'image', 'text'])
|
|||||||
<HeroSection id="hero" />
|
<HeroSection id="hero" />
|
||||||
<ImageSection id="image" />
|
<ImageSection id="image" />
|
||||||
<TextSection id="text" />
|
<TextSection id="text" />
|
||||||
|
|
||||||
<div class="indicator">
|
|
||||||
Aktuelle Section: {{ currentSection }}
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user