import gsap from "gsap"; import * as THREE from "three"; const ANIMATION = { NDS_CAMERA_POSITION: new THREE.Vector3(0, 14, 10), NDS_CAMERA_ROTATION: new THREE.Euler(THREE.MathUtils.degToRad(-55), 0, 0), GALLERY_CAMERA_POSITION: new THREE.Vector3(0, 4.5, -3), GALLERY_CAMERA_ROTATION: new THREE.Euler(THREE.MathUtils.degToRad(-62), 0, 0), CAMERA_DURATION: 3, CAMERA_ROTATION_OVERLAP: 0.1, FADE_DURATION: 1, FADE_CAMERA_OVERLAP: 0.9, NAVIGATE_DELAY: 3150, }; export const useGalleryStore = defineStore("gallery", { state: () => ({ intro: { fadeOpacity: 0, }, outro: { fadeOpacity: 1, }, isIntro: true, isOutro: false, shouldAnimateOutro: false, }), actions: { animateIntro() { this.isIntro = true; this.isOutro = false; const app = useAppStore(); // Intro: Fade starts first (at 0), camera starts after with overlap const cameraDelay = ANIMATION.FADE_DURATION - ANIMATION.FADE_CAMERA_OVERLAP; gsap.fromTo( this.intro, { fadeOpacity: 0 }, { fadeOpacity: 1, duration: ANIMATION.FADE_DURATION, delay: 0, ease: "none", }, ); if (app.camera) { gsap.fromTo( app.camera.position, { x: ANIMATION.NDS_CAMERA_POSITION.x, y: ANIMATION.NDS_CAMERA_POSITION.y, z: ANIMATION.NDS_CAMERA_POSITION.z, }, { x: ANIMATION.GALLERY_CAMERA_POSITION.x, y: ANIMATION.GALLERY_CAMERA_POSITION.y, z: ANIMATION.GALLERY_CAMERA_POSITION.z, duration: ANIMATION.CAMERA_DURATION, delay: cameraDelay, ease: "power2.inOut", }, ); gsap.fromTo( app.camera.rotation, { x: ANIMATION.NDS_CAMERA_ROTATION.x, y: ANIMATION.NDS_CAMERA_ROTATION.y, z: ANIMATION.NDS_CAMERA_ROTATION.z, }, { x: ANIMATION.GALLERY_CAMERA_ROTATION.x, y: ANIMATION.GALLERY_CAMERA_ROTATION.y, z: ANIMATION.GALLERY_CAMERA_ROTATION.z, duration: ANIMATION.CAMERA_DURATION * (1 - ANIMATION.CAMERA_ROTATION_OVERLAP), delay: cameraDelay, ease: "power2.inOut", }, ); } setTimeout(() => { this.shouldAnimateOutro = true; navigateTo("/gallery"); }, ANIMATION.NAVIGATE_DELAY); }, animateOutro() { this.isIntro = false; this.isOutro = true; const app = useAppStore(); // Outro: Camera starts first (at 0), fade starts after with overlap const fadeDelay = ANIMATION.CAMERA_DURATION - ANIMATION.FADE_CAMERA_OVERLAP; if (app.camera) { gsap.fromTo( app.camera.position, { x: ANIMATION.GALLERY_CAMERA_POSITION.x, y: ANIMATION.GALLERY_CAMERA_POSITION.y, z: ANIMATION.GALLERY_CAMERA_POSITION.z, }, { x: ANIMATION.NDS_CAMERA_POSITION.x, y: ANIMATION.NDS_CAMERA_POSITION.y, z: ANIMATION.NDS_CAMERA_POSITION.z, duration: ANIMATION.CAMERA_DURATION, delay: 0, ease: "power2.inOut", }, ); gsap.fromTo( app.camera.rotation, { x: ANIMATION.GALLERY_CAMERA_ROTATION.x, y: ANIMATION.GALLERY_CAMERA_ROTATION.y, z: ANIMATION.GALLERY_CAMERA_ROTATION.z, }, { x: ANIMATION.NDS_CAMERA_ROTATION.x, y: ANIMATION.NDS_CAMERA_ROTATION.y, z: ANIMATION.NDS_CAMERA_ROTATION.z, duration: ANIMATION.CAMERA_DURATION * (1 - ANIMATION.CAMERA_ROTATION_OVERLAP), delay: 0, ease: "power2.inOut", }, ); } gsap.fromTo( this.outro, { fadeOpacity: 1 }, { fadeOpacity: 0, duration: ANIMATION.FADE_DURATION, delay: fadeDelay, ease: "none", }, ); setTimeout(() => { this.isOutro = false; app.navigateTo("home"); }, ANIMATION.NAVIGATE_DELAY); }, }, });