fix: gsap scroll fixes at routing

This commit is contained in:
T-A-H-prog
2026-08-12 21:34:07 +02:00
parent 02fcc75790
commit 0216885738
12 changed files with 296 additions and 31 deletions

View File

@@ -1,10 +1,13 @@
<script setup lang="js"></script> <script setup lang="js"></script>
<template> <template>
<router-view /> <router-view v-slot="{ Component }">
<Transition name="page" mode="out-in">
<component :is="Component" />
</Transition>
</router-view>
</template> </template>
<style> <style>
/* Global Reset */
*, *,
*::before, *::before,
*::after { *::after {
@@ -29,4 +32,14 @@ body {
url("/src/assets/retro_cursor.svg") 2 0, url("/src/assets/retro_cursor.svg") 2 0,
auto; auto;
} }
.page-enter-active,
.page-leave-active {
transition: opacity 0.4s ease;
}
.page-enter-from,
.page-leave-to {
opacity: 0;
}
</style> </style>

View File

@@ -13,7 +13,6 @@ import gsap from "gsap";
import ScrollTrigger from "gsap/ScrollTrigger"; import ScrollTrigger from "gsap/ScrollTrigger";
import Flip from "gsap/dist/Flip"; import Flip from "gsap/dist/Flip";
(gsap.registerPlugin(ScrollTrigger), gsap.registerPlugin(Flip)); (gsap.registerPlugin(ScrollTrigger), gsap.registerPlugin(Flip));
const section = ref(null); const section = ref(null);
@@ -50,9 +49,7 @@ const createTween = () => {
.add(flip); .add(flip);
}; };
onMounted(() => { onMounted(() => {
ctx = gsap.context(() => { ctx = gsap.context(() => {
createTween(); createTween();
@@ -69,8 +66,6 @@ onMounted(() => {
onUnmounted(() => { onUnmounted(() => {
ctx?.revert(); ctx?.revert();
}); });
</script> </script>
<template> <template>
<section class="image-section" ref="section"> <section class="image-section" ref="section">
@@ -107,7 +102,7 @@ onUnmounted(() => {
</div> </div>
</div> </div>
<div class="text"> <div class="text">
<h2>Was ist Kunst?</h2> <h2>Tom Herpel</h2>
<p> <p>
Nach Schelling ist die Kunst das Erzeugnis oder die Folge jener Nach Schelling ist die Kunst das Erzeugnis oder die Folge jener
Weltanschauung, nach der das Subjekt sich in sein Objekt verwandelt oder Weltanschauung, nach der das Subjekt sich in sein Objekt verwandelt oder

View File

@@ -111,12 +111,7 @@ function getTimeDate() {
<div class="b-three"></div> <div class="b-three"></div>
<div class="b-four"></div> <div class="b-four"></div>
<div class="b-five"></div> <div class="b-five"></div>
<div class="b-six" text> <div class="b-six" text></div>
Die Schweizer**
<a href="https://en.wikipedia.org/wiki/Swiss_Style_(design)">
https://en.wikipedia.org/wiki/Swiss_Style_(design)
</a>
</div>
<div class="textblock text"> <div class="textblock text">
<h4 class="text fontStyle">Tom Alexander Herpel</h4> <h4 class="text fontStyle">Tom Alexander Herpel</h4>

View File

@@ -215,7 +215,7 @@ onUnmounted(() => {
resizeObserver.disconnect(); resizeObserver.disconnect();
renderer?.dispose(); renderer?.dispose();
gsapCtx?.revert(); gsapCtx?.revert();
ScrollTrigger.getAll().forEach((t) => t.kill()); // ScrollTrigger.getAll().forEach((t) => t.kill());
}); });
</script> </script>
<template> <template>

View File

@@ -69,11 +69,11 @@ window.addEventListener("resize", createTimeline);
<div class="container second"> <div class="container second">
<div class="experience-text"> <div class="experience-text">
<h2>Enten?</h2> <h2>About Me</h2>
</div> </div>
<div class="marker"></div> <div class="marker"></div>
<router-link to="/books"> <router-link to="/motion/me">
<button class="btn second-btn">Books i've read</button> <button class="btn second-btn">Get to know me</button>
</router-link> </router-link>
</div> </div>
<div class="container third"> <div class="container third">
@@ -193,7 +193,7 @@ body {
.experience-text h2 { .experience-text h2 {
font-size: 1.2rem; font-size: 1.2rem;
color: white; color: #7c7c6f;
margin: 0; margin: 0;
} }

View File

@@ -78,6 +78,9 @@ onMounted(async () => {
ctx = gsap.context(() => { ctx = gsap.context(() => {
initParallax(parallaxRef.value); initParallax(parallaxRef.value);
// initChild(); // initChild();
requestAnimationFrame(() => {
ScrollTrigger.refresh();
});
initLenis(); initLenis();
}); });
}); });
@@ -213,6 +216,7 @@ onUnmounted(() => {
left: 0; left: 0;
} }
.parallax__title { .parallax__title {
color: antiquewhite;
pointer-events: auto; pointer-events: auto;
text-align: center; text-align: center;
text-transform: none; text-transform: none;

View File

@@ -3,12 +3,12 @@
<div class="parent"> <div class="parent">
<!-- TOP LEFT --> <!-- TOP LEFT -->
<div class="div3"> <div class="div3">
<span>Portfolio / 01</span> <span>About me / 01</span>
</div> </div>
<!-- TOP CENTER --> <!-- TOP CENTER -->
<div class="div12"> <div class="div12">
<span>About me</span> <span>TH</span>
</div> </div>
<!-- TOP RIGHT --> <!-- TOP RIGHT -->

View File

@@ -80,7 +80,7 @@
<span class="arrow">↓</span> <span class="arrow">↓</span>
</section> </section>
<section class="div22 location"> <section class="div22 location" @click="$router.push('/motion')">
<span>Location</span> <span>Location</span>
<div class="location-name"> <div class="location-name">

View File

@@ -1,13 +1,16 @@
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router' import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'
import HomeBig from '../views/HomeBig.vue' import HomeBig from '../views/HomeBig.vue'
import DucksInfo from '../views/InfoDucks.vue' // import DucksInfo from '../views/InfoDucks.vue'
import BooksShow from '../views/BooksShow.vue' import BooksShow from '../views/BooksShow.vue'
import SlimMain from '../views/HomeSlime.vue' import SlimMain from '../views/HomeSlime.vue'
import BigMeImg from '../views/ImageSection.vue'
const routes: RouteRecordRaw[] = [ const routes: RouteRecordRaw[] = [
{ path: '/', component: SlimMain }, { path: '/', component: SlimMain },
{path: '/ducks', component: DucksInfo}, { path: '/motion', component: HomeBig },
{path: '/motion/me', component: BigMeImg},
{path: '/books', component: BooksShow} {path: '/books', component: BooksShow}
// { path: '/ducks', // { path: '/ducks',

View File

@@ -3,7 +3,7 @@ import WelcomeSection from "../components/big/WelcomeSection.vue";
import TextSection from "../components/big/TextSection.vue"; import TextSection from "../components/big/TextSection.vue";
import { onMounted, nextTick } from "vue"; import { onMounted, nextTick, onUnmounted } 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";
@@ -13,6 +13,8 @@ import IntroductionSection from "../components/big/IntroductionSection.vue";
gsap.registerPlugin(ScrollTrigger, ScrollSmoother); gsap.registerPlugin(ScrollTrigger, ScrollSmoother);
let smoother: ScrollSmoother | null = null;
onMounted(async () => { onMounted(async () => {
await nextTick(); await nextTick();
@@ -25,6 +27,13 @@ onMounted(async () => {
ScrollTrigger.refresh(); ScrollTrigger.refresh();
}); });
onUnmounted(() => {
smoother?.kill();
smoother = null;
ScrollTrigger.getAll().forEach((trigger) => trigger.kill());
});
</script> </script>
<template> <template>
@@ -33,7 +42,7 @@ onMounted(async () => {
<WelcomeSection id="welcome" /> <WelcomeSection id="welcome" />
<!-- <NewTextSection id="newText" /> --> <!-- <NewTextSection id="newText" /> -->
<IntroductionSection id="welcome" /> <IntroductionSection />
<MonitorModel id="model" /> <MonitorModel id="model" />
<!-- <HeroSection id="hero" /> --> <!-- <HeroSection id="hero" /> -->
<!-- <ImageSection id="image" /> --> <!-- <ImageSection id="image" /> -->

View File

@@ -4,10 +4,9 @@ import AboutMe from "../components/slim/AboutMe.vue";
import { onMounted, nextTick } from "vue"; import { onMounted, nextTick } from "vue";
import gsap from "gsap"; import gsap from "gsap";
import ScrollTrigger from "gsap/ScrollTrigger";
import ScrollSmoother from "gsap/ScrollSmoother"; import ScrollSmoother from "gsap/ScrollSmoother";
gsap.registerPlugin(ScrollTrigger, ScrollSmoother); gsap.registerPlugin(ScrollSmoother);
onMounted(async () => { onMounted(async () => {
await nextTick(); await nextTick();
@@ -15,11 +14,9 @@ onMounted(async () => {
ScrollSmoother.create({ ScrollSmoother.create({
wrapper: "#smooth-wrapper", wrapper: "#smooth-wrapper",
content: "#smooth-content", content: "#smooth-content",
smooth: 0.2, smooth: 1.5,
effects: true, effects: true,
}); });
ScrollTrigger.refresh();
}); });
</script> </script>

249
src/views/ImageSection.vue Normal file
View File

@@ -0,0 +1,249 @@
<script setup lang="js">
import ski from "../assets/myself/ski.png";
import book from "../assets/myself/SmartTom.jpeg";
import surf from "../assets/myself/surf.png";
import boxen from "../assets/myself/TOm.jpg";
import florencs from "../assets/myself/15.jpg";
import schnee from "../assets/myself/DSCN1921.jpg";
import water from "../assets/myself/27-2.jpg";
import gopro from "../assets/myself/GOPR0521.png";
import { ref, onMounted, onUnmounted } from "vue";
import gsap from "gsap";
import ScrollTrigger from "gsap/ScrollTrigger";
import Flip from "gsap/dist/Flip";
(gsap.registerPlugin(ScrollTrigger), gsap.registerPlugin(Flip));
const section = ref(null);
const gallery = ref(null);
const img_daten = ref(null);
let ctx;
let flipCtx;
const createTween = () => {
const galleryElement = gallery.value;
const galleryItems = galleryElement.querySelectorAll(".gallery__item");
galleryElement.classList.add("gallery--final");
const state = Flip.getState(galleryItems);
galleryElement.classList.remove("gallery--final");
const flip = Flip.to(state, {
simple: true,
ease: "expoScale(1,5)",
});
gsap
.timeline({
scrollTrigger: {
trigger: galleryElement,
start: "center center",
end: "+=100%",
scrub: true,
pin: galleryElement.parentNode,
invalidateOnRefresh: true,
},
})
.add(flip);
};
onMounted(() => {
ctx = gsap.context(() => {
createTween();
window.addEventListener("resize", () => {
ScrollTrigger.refresh();
});
}, section.value);
requestAnimationFrame(() => {
ScrollTrigger.refresh();
});
});
onUnmounted(() => {
ctx?.revert();
});
</script>
<template>
<section class="image-section" ref="section">
<div class="gallery-wrap">
<div
class="gallery gallery--bento gallery--switch"
id="gallery-8"
ref="gallery"
>
<div class="gallery__item">
<img :src="ski" alt="" />
</div>
<div class="gallery__item">
<img :src="schnee" alt="" />
</div>
<div class="gallery__item">
<img :src="schnee" alt="" />
</div>
<div class="gallery__item">
<img :src="schnee" alt="" />
</div>
<div class="gallery__item">
<img :src="schnee" alt="" />
</div>
<div class="gallery__item">
<img :src="book" alt="" />
</div>
<div class="gallery__item">
<img :src="ski" alt="" />
</div>
<div class="gallery__item">
<img :src="water" alt="" />
</div>
</div>
</div>
<div class="text">
<h2>Was ist Kunst?</h2>
<p>
Nach Schelling ist die Kunst das Erzeugnis oder die Folge jener
Weltanschauung, nach der das Subjekt sich in sein Objekt verwandelt oder
das Objekt selbst 45 zum Subjekt wird. Die Schönheit ist die Darstellung
des Unendli- chen im Endlichen. Und der Grundcharakter eines Kunstwerkes
ist die bewußtlose Unendlichkeit. Die Kunst ist die Vereinigung des
Subjektiven mit dem Objektiven, – der Natur mit der Vernunft, der
Bewußtlosigkeit mit dem Bewußten. Und deshalb ist die Kunst das höchste
Mittel der Erkenntnis. Die Schönheit ist die Betrachtung der Dinge an
sich, wie sie in Urbildern sind. Das Schöne erzeugt nicht der Künstler
vermöge seines Wissens oder seines Willens, sondern die Idee der
Schönheit selbst schafft in ihm. (Schaßler)
</p>
<p>
In der Welt erblicken wir nur die Entartung der Grundidee, die Kunst
jedoch kann ver- möge der Phantasie sich bis zur Höhe der Grundidee
erheben. Und deshalb ist die Kunst das Ebenbild der Schöpfung
(Schaßler).
</p>
<p>
Nach einem anderen Anhänger Schellings, Krause (1781–1832), ist die
wahre reale Schönheit die Erzeugung der Idee in der indivi- duellen
Form; die Kunst ist aber die Verwirklichung der Schönheit in der Sphäre
des freien menschlichen Geistes. Die höchste Stufe der Kunst ist die
Kunst des Lebens, die ihre Thätigkeit auf die Verschö- nerung des Lebens
richtet, damit dies ein schön belebter Wohnort für die selber in
Schönheit vollendete Menschheit sei. (Ebd.)
</p>
<p>
Nach Hegel (1770–1831) offenbart sich Gott in Natur und Kunst unter der
Form der Schönheit. Gott äußert sich auf zweierlei Weise: in dem Objekt
und in dem Subjekt, – in der Natur und im Geiste. Die Schönheit ist
jedoch das Durch- scheinen der Idee durch den Stoff. Das wahrhaft Schöne
ist nur der Geist und alles das, was dem Geiste teilhaftig ist. Deshalb
ist die Schönheit der Natur nur der Schein der dem Geiste eigenen Schön-
heit: das Schöne hat nur als Geistiges wahrhaften Gehalt. Aber das
Geistige muß in der sinnlichen Form erscheinen. Die sinnliche Äu- ßerung
des Geistes jedoch ist nur der Schein. Und dieser Schein ist die
eigentliche Wirklichkeit des Schönen. Sodaß die Kunst die 46
Verwirklichung dieses Scheines der Idee und zugleich mit der Reli- gion
und Philosophie das Mittel ist, die tiefsten Interessen der Men- schen
und die umfassendsten Wahrheiten des Geistes zum Bewußt- sein zu bringen
und auszusprechen. Wahrheit und Schönheit sind nach Hegel ein und
dasselbe: der Unterschied besteht nur darin, daß die Wahrheit die Idee
ist, wie diese an sich und dem allgemeinen Prinzip nach ist und als
solches gedacht wird. Die Idee jedoch, die äußerlich existiert, wird für
das Bewußtsein nicht blos wahr, son- dern auch schön. Das Schöne ist das
Scheinen der Idee
</p>
<p>
--- Was ist Kunst?, Leo N. Tolstoi, Aus dem Russischen von Michail
Feofanov (1902) ---
</p>
</div>
</section>
</template>
<style scoped>
p {
font-size: 1.2rem;
margin-bottom: 1rem;
}
.gallery-wrap {
position: relative;
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.gallery {
position: relative;
width: 100%;
height: 100%;
flex: none;
}
.gallery__item {
background-position: 50% 50%;
background-size: cover;
flex: none;
position: relative;
img {
object-fit: cover;
width: 100%;
height: 100%;
}
}
.gallery--bento {
display: grid;
gap: 1vh;
grid-template-columns: repeat(3, 32.5vw);
grid-template-rows: repeat(4, 23vh);
justify-content: center;
align-content: center;
}
.gallery--final.gallery--bento {
grid-template-columns: repeat(3, 100vw);
grid-template-rows: repeat(4, 49.5vh);
gap: 1vh;
}
.gallery--bento .gallery__item:nth-child(1) {
grid-area: 1 / 1 / 3 / 2;
}
.gallery--bento .gallery__item:nth-child(2) {
grid-area: 1 / 2 / 2 / 3;
}
.gallery--bento .gallery__item:nth-child(3) {
grid-area: 2 / 2 / 4 / 3;
}
.gallery--bento .gallery__item:nth-child(4) {
grid-area: 1 / 3 / 3 / 3;
}
.gallery--bento .gallery__item:nth-child(5) {
grid-area: 3 / 1 / 3 / 2;
}
.gallery--bento .gallery__item:nth-child(6) {
grid-area: 3 / 3 / 5 / 4;
}
.gallery--bento .gallery__item:nth-child(7) {
grid-area: 4 / 1 / 5 / 2;
}
.gallery--bento .gallery__item:nth-child(8) {
grid-area: 4 / 2 / 5 / 3;
}
.text {
font-family: Courier New;
padding: 2rem 5rem;
}
</style>