Files
pihkaal-me/app/stores/gallery.ts

164 lines
4.2 KiB
TypeScript

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);
},
},
});