This commit is contained in:
T-A-H-prog
2026-08-13 22:14:16 +02:00
parent 16d4bf1e4b
commit 78e35694bd
4 changed files with 223 additions and 26 deletions

View File

@@ -74,13 +74,26 @@
<span class="number">03 / 04</span>
</div>
<div>
<span class="label">Based in</span>
<div class="interests">
<span class="label">Misc</span>
<p class="small location">
Germany<br />
Europe
</p>
<ul class="interessen-list">
<li
v-for="(interest, index) in interests"
:key="interest.name"
@click="emit('morphTo', interest.target)"
>
<span class="number">
{{ String(index + 1).padStart(2, "0") }}
</span>
<span class="interest-name">
{{ interest.name }}
</span>
<span class="arrow">↗</span>
</li>
</ul>
</div>
</section>
@@ -99,8 +112,35 @@
</main>
</template>
<script setup>
<script setup lang="ts">
import tom_img from "../../assets/myself/SmartTom.jpeg";
const interests = [
{
name: "Goals",
target: "#goals",
},
{
name: "Coding",
target: "#coding",
},
{
name: "Videos",
target: "#videos",
},
{
name: "Books",
target: "#books",
},
{
name: "Experiences",
target: "#experiences",
},
];
const emit = defineEmits<{
morphTo: [target: string];
}>();
</script>
<style scoped>
@@ -317,10 +357,16 @@ import tom_img from "../../assets/myself/SmartTom.jpeg";
font-weight: 700;
letter-spacing: 0.08em;
}
.interests {
width: 100%;
}
.label {
font-size: 11px;
font-weight: 700;
display: block;
margin-bottom: 30px;
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.08em;
}
@@ -357,16 +403,63 @@ import tom_img from "../../assets/myself/SmartTom.jpeg";
font-weight: 700;
}
.skill-list li {
.skill-list li,
.interressen-list li {
padding: 6px 0;
border-top: 1px solid rgba(41, 37, 31, 0.35);
}
.skill-list li:last-child {
/*
.skill-list li:last-child,
.interressen-list li:last-child {
border-bottom: 1px solid rgba(41, 37, 31, 0.35);
} */
.interessen-list li {
display: grid;
grid-template-columns: 50px 1fr 30px;
align-items: center;
min-height: 70px;
border-top: 1px solid rgba(31, 31, 31, 0.35);
cursor: pointer;
transition:
padding-left 0.4s cubic-bezier(0.22, 1, 0.36, 1),
background-color 0.3s ease;
}
.interessen-list li:last-child {
border-bottom: none;
}
.number {
font-size: 12px;
color: #777;
}
.interest-name {
font-size: clamp(24px, 3vw, 42px);
font-weight: 500;
line-height: 1;
letter-spacing: -0.04em;
}
.arrow {
font-size: 24px;
justify-self: end;
transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
}
.interessen-list li:hover {
padding-left: 20px;
}
.interessen-list li:hover .arrow {
transform: translateX(8px) rotate(45deg);
}
.footer-links {
display: flex;
gap: 25px;

View File

@@ -0,0 +1,11 @@
<template>
<h2 @click="emit('morphTo', '#me')">Hallo</h2>
</template>
<script setup lang="ts">
const emit = defineEmits<{
morphTo: [target: string];
}>();
</script>
<style lang="scss" scoped></style>

View File

@@ -17,9 +17,9 @@
</div>
</section>
<button class="div14 nav-item">
<button class="div14 nav-item" @click="emit('scrollToNext', '#me')">
<span>01</span>
<span>About</span>
<span>About Me</span>
</button>
<button class="div15 nav-item">
@@ -82,7 +82,7 @@
</div>
</section>
<section class="div21 small-block">
<section class="div21 small-block" @click="emit('scrollToNext', '#me')">
<span>03</span>
<span>Scroll</span>
<span class="arrow">↓</span>
@@ -106,8 +106,11 @@
</main>
</template>
<script setup>
<script setup lang="ts">
import { ref } from "vue";
const emit = defineEmits<{
scrollToNext: [target: string];
}>();
const isInteractiveHovered = ref(false);
</script>

View File

@@ -1,42 +1,132 @@
<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 { onMounted, onUnmounted, nextTick } 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.5,
smooth: 1.8,
effects: true,
});
ScrollTrigger.refresh();
});
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(() => {
smoother?.kill();
if (smoother) {
smoother.kill();
smoother = null;
}
});
</script>
<template>
<div id="smooth-wrapper">
<div id="smooth-content">
<Main id="welcome" />
<AboutMe id="me" />
<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 lang="css" scoped></style>
<style scoped>
.component-wrapper {
position: relative;
width: 100%;
}
#me,
#goals {
width: 100%;
}
#goals {
position: absolute;
inset: 0;
opacity: 0;
pointer-events: none;
}
</style>