This commit is contained in:
T-A-H-prog
2026-04-15 21:25:37 +02:00
parent c032578bc6
commit c861603b06
3 changed files with 80 additions and 40 deletions

View File

@@ -5,9 +5,10 @@ import gsap from "gsap";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"; import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js"; import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
const canvasRef = ref(null); const canvasRef = ref(null);
let renderer, scene, camera, model; let renderer, scene, camera, model, controls;
function initThree(canvas) { function initThree(canvas) {
renderer = new THREE.WebGLRenderer({ renderer = new THREE.WebGLRenderer({
@@ -18,13 +19,20 @@ function initThree(canvas) {
renderer.outputColorSpace = THREE.SRGBColorSpace; renderer.outputColorSpace = THREE.SRGBColorSpace;
scene = new THREE.Scene(); scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100); camera = new THREE.PerspectiveCamera(45, 2, 0.1, 100);
camera.position.set(0, 0, 5); camera.position.set(0, 0, 5);
const light = new THREE.DirectionalLight(0xffffff, 1); const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(2, 2, 5); light.position.set(2, 2, 5);
scene.add(light); scene.add(light);
controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.minDistance = 5;
controls.maxDistance = 5;
controls.maxPolarAngle = Math.PI / 2;
scene.add(new THREE.AmbientLight(0xffffff, 0.5)); scene.add(new THREE.AmbientLight(0xffffff, 0.5));
loadModel(); loadModel();
@@ -53,6 +61,10 @@ function loadModel() {
const box = new THREE.Box3().setFromObject(model); const box = new THREE.Box3().setFromObject(model);
const center = box.getCenter(new THREE.Vector3()); const center = box.getCenter(new THREE.Vector3());
const size = box.getSize(new THREE.Vector3()); const size = box.getSize(new THREE.Vector3());
controls.target.copy(center);
controls.update();
model.position.set(0, 0, 0); model.position.set(0, 0, 0);
scene.add(model); scene.add(model);
@@ -72,11 +84,14 @@ function loadModel() {
function render() { function render() {
if (!renderer) return; if (!renderer) return;
controls.update();
renderer.render(scene, camera); renderer.render(scene, camera);
} }
function onResize() { function onResize() {
if (!renderer || !canvasRef.value) return; if (!renderer || !canvasRef.value) return;
const r = canvasRef.getBoundingClientRect(); const r = canvasRef.value.getBoundingClientRect();
const dpr = Math.min(window.devicePixelRatio || 1, 2); const dpr = Math.min(window.devicePixelRatio || 1, 2);
const width = canvasRef.value.clientWidth; const width = canvasRef.value.clientWidth;
@@ -89,21 +104,26 @@ function onResize() {
camera.updateProjectionMatrix(); camera.updateProjectionMatrix();
} }
const resizeObserver = new ResizeObserver(onResize);
onMounted(() => { onMounted(() => {
initThree(canvasRef.value); initThree(canvasRef.value);
onResize(); onResize();
resizeObserver.observe(canvasRef.value);
window.addEventListener("resize", onResize); window.addEventListener("resize", onResize);
}); });
onUnmounted(() => { onUnmounted(() => {
gsap.ticker.remove(render); gsap.ticker.remove(render);
window.removeEventListener("resize", onResize); window.removeEventListener("resize", onResize);
resizeObserver.disconnect();
renderer?.dispose(); renderer?.dispose();
}); });
</script> </script>
<template> <template>
<div class="wrapper"> <div class="wrapper">
<div class="spacer">Scroll Down</div> <div class="spacer"></div>
<canvas class="canvas" ref="canvasRef"></canvas> <canvas class="canvas" ref="canvasRef"></canvas>
</div> </div>
@@ -117,7 +137,10 @@ onUnmounted(() => {
place-items: center; place-items: center;
font-weight: 600; font-weight: 600;
} }
.canvas { .canvas {
width: 100%;
height: 100%;
display: block; display: block;
} }
</style> </style>

View File

@@ -48,21 +48,20 @@ const createTimeline = () => {
onMounted(() => { onMounted(() => {
createTimeline(); createTimeline();
window.addEventListener("resize", createTimeline);
window.addEventListener("resize", createTween);
ScrollTrigger.refresh(); ScrollTrigger.refresh();
}); });
onUnmounted(() => { onUnmounted(() => {
flipCtx?.revert(); flipCtx?.revert();
window.removeEventListener("resize", createTween); window.removeEventListener("resize", createTimeline);
gsap.ticker.remove(updateMorph);
}); });
window.addEventListener("resize", createTimeline); window.addEventListener("resize", createTimeline);
</script> </script>
<template> <template>
<section class="text-section">
<div class="main"> <div class="main">
<div class="container initial"> <div class="container initial">
<div class="circle"></div> <div class="circle"></div>
@@ -87,6 +86,7 @@ window.addEventListener("resize", createTimeline);
</div> </div>
</div> </div>
<div class="spacer final"></div> <div class="spacer final"></div>
</section>
</template> </template>
<style scoped> <style scoped>

View File

@@ -1,5 +1,5 @@
<script setup> <script setup>
import { onMounted, onUnmounted } from "vue"; import { onMounted, onUnmounted, ref, nextTick } from "vue";
import MonitorModel from "/src/components/sections/MonitorModel.vue"; import MonitorModel from "/src/components/sections/MonitorModel.vue";
@@ -12,9 +12,11 @@ import Lenis from "lenis";
gsap.registerPlugin(ScrollTrigger); gsap.registerPlugin(ScrollTrigger);
let ctx; let ctx, lenis;
const childRef = ref(null);
const parallaxRef = ref(null);
function initParallax() { function initParallax(triggerElement) {
const layers = [ const layers = [
{ layer: "1", yPercent: 70 }, { layer: "1", yPercent: 70 },
{ layer: "2", yPercent: 50 }, { layer: "2", yPercent: 50 },
@@ -22,8 +24,6 @@ function initParallax() {
{ layer: "4", yPercent: 10 }, { layer: "4", yPercent: 10 },
]; ];
const triggerElement = document.querySelector(".parallax");
const tl = gsap.timeline({ const tl = gsap.timeline({
scrollTrigger: { scrollTrigger: {
trigger: triggerElement, trigger: triggerElement,
@@ -46,6 +46,17 @@ function initParallax() {
); );
}); });
} }
function initChild() {
gsap.to(childRef.value, {
scrollTrigger: {
trigger: childRef.value,
start: "top center",
},
scale,
});
}
function initLenis() { function initLenis() {
lenis = new Lenis({ lenis = new Lenis({
duration: 1.1, duration: 1.1,
@@ -61,20 +72,23 @@ function initLenis() {
gsap.ticker.lagSmoothing(0); gsap.ticker.lagSmoothing(0);
} }
onMounted(() => { onMounted(async () => {
await nextTick();
ctx = gsap.context(() => { ctx = gsap.context(() => {
initParallax(); initParallax(parallaxRef.value);
// initChild();
initLenis(); initLenis();
}); });
}); });
onUnmounted(() => { onUnmounted(() => {
ctx?.revert(); ctx?.revert();
lenis?.destroy(); lenis?.destroy();
}); });
</script> </script>
<template> <template>
<div class="parallax"> <div ref="parallaxRef" class="parallax">
<section class="parallax__header"> <section class="parallax__header">
<div class="parallax__visuals"> <div class="parallax__visuals">
<div class="parallax__layers"> <div class="parallax__layers">
@@ -91,7 +105,7 @@ onUnmounted(() => {
/> />
<div data-parallax-layer="3" class="parallax__layer-title"> <div data-parallax-layer="3" class="parallax__layer-title">
<h2 class="parallax__title">WELCOM</h2> <h2 class="parallax__title">TOM HERPEL</h2>
</div> </div>
<img data-parallax-layer="4" class="parallax__layer-img" /> <img data-parallax-layer="4" class="parallax__layer-img" />
@@ -102,7 +116,9 @@ onUnmounted(() => {
</section> </section>
<section class="parallax__content"> <section class="parallax__content">
<div ref="childRef" class="model__wrapper">
<MonitorModel /> <MonitorModel />
</div>
</section> </section>
</div> </div>
</template> </template>
@@ -151,7 +167,7 @@ onUnmounted(() => {
.parallax__content { .parallax__content {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
min-height: 100svh; min-height: 200svh;
display: flex; display: flex;
position: relative; position: relative;
} }
@@ -249,6 +265,7 @@ onUnmounted(() => {
top: -17.5%; top: -17.5%;
left: 0; left: 0;
} }
@font-face { @font-face {
font-family: "ArtDystopia"; font-family: "ArtDystopia";
src: url("/src/assets/fonts/Art_Dystopia.woff2") format("opentype"); src: url("/src/assets/fonts/Art_Dystopia.woff2") format("opentype");