Files
th-website/src/views/HomeSlime.vue
T-A-H-prog 78e35694bd morph
2026-08-13 22:14:16 +02:00

133 lines
2.4 KiB
Vue

<script setup lang="ts">
import Main from "../components/slim/Main.vue";
import AboutMe from "../components/slim/AboutMe.vue";
import Goals from "../components/slim/Goals.vue";
import { onMounted, onUnmounted, nextTick, ref } from "vue";
import gsap from "gsap";
import ScrollTrigger from "gsap/ScrollTrigger";
import ScrollSmoother from "gsap/ScrollSmoother";
import { S } from "vue-router/dist/router-CWoNjPRp.mjs";
gsap.registerPlugin(ScrollTrigger, ScrollSmoother);
let smoother: ScrollSmoother | null = null;
const transitioning = ref(false);
onMounted(async () => {
await nextTick();
if (smoother) return;
smoother = ScrollSmoother.create({
wrapper: "#smooth-wrapper",
content: "#smooth-content",
smooth: 1.8,
effects: true,
});
});
const scrollTo = (target: string) => {
if (!smoother) return;
smoother.scrollTo(target, true);
};
const morphTo = (target: string) => {
if (transitioning.value) return;
const current =
target === "#goals"
? document.querySelector("#me")
: document.querySelector("#goals");
const next = document.querySelector(target);
if (!current || !next) return;
transitioning.value = true;
gsap.set(next, {
opacity: 0,
scale: 0.85,
filter: "blur(20px)",
clipPath: "circle(0% at 50% 50%)",
pointerEvents: "none",
});
gsap.set(current, {
transformOrigin: "50% 50%",
});
const tl = gsap.timeline({
onComplete: () => {
transitioning.value = false;
scrollTo(target);
},
});
tl.to(current, {
scale: 0.92,
opacity: 0,
filter: "blur(15px)",
duration: 0.4,
ease: "power1.in",
})
.set(next, {
opacity: 1,
pointerEvents: "auto",
})
.to(next, {
scale: 1,
filter: "blur(0px)",
clipPath: "circle(150% at 50% 50%)",
duration: 0.8,
ease: "power4.inOut",
});
};
onUnmounted(() => {
if (smoother) {
smoother.kill();
smoother = null;
}
});
</script>
<template>
<div id="smooth-wrapper">
<div id="smooth-content">
<Main id="welcome" @scroll-to-next="scrollTo" />
<section class="component-wrapper">
<AboutMe id="me" @morph-to="morphTo" />
<Goals id="goals" @morph-to="morphTo" />
</section>
</div>
</div>
</template>
<style scoped>
.component-wrapper {
position: relative;
width: 100%;
}
#me,
#goals {
width: 100%;
}
#goals {
position: absolute;
inset: 0;
opacity: 0;
pointer-events: none;
}
</style>