new components
This commit is contained in:
11
src/components/slim/interressen/Books.vue
Normal file
11
src/components/slim/interressen/Books.vue
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<template>
|
||||||
|
<h2 @click="emit('morphTo', '#me')">Books</h2>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
const emit = defineEmits<{
|
||||||
|
morphTo: [target: string];
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
11
src/components/slim/interressen/Coding.vue
Normal file
11
src/components/slim/interressen/Coding.vue
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<template>
|
||||||
|
<h2 @click="emit('morphTo', '#me')">Coding</h2>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
const emit = defineEmits<{
|
||||||
|
morphTo: [target: string];
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<h2 @click="emit('morphTo', '#me')">Hallo</h2>
|
<h2 @click="emit('morphTo', '#me')">Goals</h2>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
11
src/components/slim/interressen/Videos.vue
Normal file
11
src/components/slim/interressen/Videos.vue
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<template>
|
||||||
|
<h2 @click="emit('morphTo', '#me')">Videos</h2>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
const emit = defineEmits<{
|
||||||
|
morphTo: [target: string];
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
@@ -1,14 +1,16 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Main from "../components/slim/Main.vue";
|
import Main from "../components/slim/Main.vue";
|
||||||
import AboutMe from "../components/slim/AboutMe.vue";
|
import AboutMe from "../components/slim/AboutMe.vue";
|
||||||
import Goals from "../components/slim/Goals.vue";
|
import Goals from "../components/slim/interressen/Goals.vue";
|
||||||
|
import Coding from "../components/slim/interressen/Coding.vue";
|
||||||
|
import Books from "../components/slim/interressen/Books.vue";
|
||||||
|
import Videos from "../components/slim/interressen/Videos.vue";
|
||||||
|
|
||||||
import { onMounted, onUnmounted, nextTick, ref } from "vue";
|
import { onMounted, onUnmounted, nextTick, ref } from "vue";
|
||||||
|
|
||||||
import gsap from "gsap";
|
import gsap from "gsap";
|
||||||
import ScrollTrigger from "gsap/ScrollTrigger";
|
import ScrollTrigger from "gsap/ScrollTrigger";
|
||||||
import ScrollSmoother from "gsap/ScrollSmoother";
|
import ScrollSmoother from "gsap/ScrollSmoother";
|
||||||
import { S } from "vue-router/dist/router-CWoNjPRp.mjs";
|
|
||||||
|
|
||||||
gsap.registerPlugin(ScrollTrigger, ScrollSmoother);
|
gsap.registerPlugin(ScrollTrigger, ScrollSmoother);
|
||||||
|
|
||||||
@@ -34,35 +36,65 @@ const scrollTo = (target: string) => {
|
|||||||
smoother.scrollTo(target, true);
|
smoother.scrollTo(target, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const currentSection = ref("#me");
|
||||||
|
|
||||||
const morphTo = (target: string) => {
|
const morphTo = (target: string) => {
|
||||||
if (transitioning.value) return;
|
if (transitioning.value) return;
|
||||||
|
|
||||||
const current =
|
// Bereits auf dieser Section? Nichts tun.
|
||||||
target === "#goals"
|
if (currentSection.value === target) return;
|
||||||
? document.querySelector("#me")
|
|
||||||
: document.querySelector("#goals");
|
|
||||||
|
|
||||||
|
const current = document.querySelector(currentSection.value);
|
||||||
const next = document.querySelector(target);
|
const next = document.querySelector(target);
|
||||||
|
|
||||||
if (!current || !next) return;
|
if (!current || !next) return;
|
||||||
|
|
||||||
transitioning.value = true;
|
transitioning.value = true;
|
||||||
|
|
||||||
|
// Ziel vorbereiten
|
||||||
gsap.set(next, {
|
gsap.set(next, {
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
scale: 0.85,
|
scale: 0.85,
|
||||||
filter: "blur(20px)",
|
filter: "blur(20px)",
|
||||||
clipPath: "circle(0% at 50% 50%)",
|
clipPath: "circle(0% at 50% 50%)",
|
||||||
pointerEvents: "none",
|
pointerEvents: "none",
|
||||||
|
zIndex: 2,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Aktuelles Element nach vorne
|
||||||
gsap.set(current, {
|
gsap.set(current, {
|
||||||
|
zIndex: 1,
|
||||||
transformOrigin: "50% 50%",
|
transformOrigin: "50% 50%",
|
||||||
|
pointerEvents: "auto",
|
||||||
});
|
});
|
||||||
|
|
||||||
const tl = gsap.timeline({
|
const tl = gsap.timeline({
|
||||||
onComplete: () => {
|
onComplete: () => {
|
||||||
|
// Aktuellen Zustand speichern
|
||||||
|
currentSection.value = target;
|
||||||
|
|
||||||
|
// Altes Element komplett deaktivieren
|
||||||
|
gsap.set(current, {
|
||||||
|
opacity: 0,
|
||||||
|
pointerEvents: "none",
|
||||||
|
scale: 1,
|
||||||
|
filter: "blur(0px)",
|
||||||
|
clipPath: "none",
|
||||||
|
zIndex: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Neues Element vollständig aktivieren
|
||||||
|
gsap.set(next, {
|
||||||
|
opacity: 1,
|
||||||
|
pointerEvents: "auto",
|
||||||
|
scale: 1,
|
||||||
|
filter: "blur(0px)",
|
||||||
|
clipPath: "none",
|
||||||
|
zIndex: 2,
|
||||||
|
});
|
||||||
|
|
||||||
transitioning.value = false;
|
transitioning.value = false;
|
||||||
|
|
||||||
scrollTo(target);
|
scrollTo(target);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -74,12 +106,10 @@ const morphTo = (target: string) => {
|
|||||||
duration: 0.4,
|
duration: 0.4,
|
||||||
ease: "power1.in",
|
ease: "power1.in",
|
||||||
})
|
})
|
||||||
|
|
||||||
.set(next, {
|
.set(next, {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
pointerEvents: "auto",
|
pointerEvents: "auto",
|
||||||
})
|
})
|
||||||
|
|
||||||
.to(next, {
|
.to(next, {
|
||||||
scale: 1,
|
scale: 1,
|
||||||
filter: "blur(0px)",
|
filter: "blur(0px)",
|
||||||
@@ -100,12 +130,15 @@ onUnmounted(() => {
|
|||||||
<template>
|
<template>
|
||||||
<div id="smooth-wrapper">
|
<div id="smooth-wrapper">
|
||||||
<div id="smooth-content">
|
<div id="smooth-content">
|
||||||
|
in d
|
||||||
<Main id="welcome" @scroll-to-next="scrollTo" />
|
<Main id="welcome" @scroll-to-next="scrollTo" />
|
||||||
|
|
||||||
<section class="component-wrapper">
|
<section class="component-wrapper">
|
||||||
<AboutMe id="me" @morph-to="morphTo" />
|
<AboutMe id="me" @morph-to="morphTo" />
|
||||||
|
|
||||||
<Goals id="goals" @morph-to="morphTo" />
|
<Goals id="goals" @morph-to="morphTo" />
|
||||||
|
<Videos id="videos" @morph-to="morphTo" />
|
||||||
|
<Coding id="coding" @morph-to="morphTo" />
|
||||||
|
<Books id="books" @morph-to="morphTo" />
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -113,16 +146,22 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.component-wrapper {
|
.component-wrapper {
|
||||||
position: relative;
|
position: relative
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#me,
|
#me,
|
||||||
#goals {
|
#goals,
|
||||||
|
#videos,
|
||||||
|
#coding,
|
||||||
|
#books {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#goals {
|
#goals,
|
||||||
|
#videos,
|
||||||
|
#coding,
|
||||||
|
#books {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user