feat(projects): intro and outro animations
This commit is contained in:
@@ -8,10 +8,20 @@ onMounted(async () => {
|
|||||||
store.$reset();
|
store.$reset();
|
||||||
await store.loadProjects();
|
await store.loadProjects();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => store.loading,
|
||||||
|
() => {
|
||||||
|
if (!store.loading) {
|
||||||
|
store.animateIntro();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<template v-if="!store.loading">
|
||||||
<Background />
|
<Background />
|
||||||
|
<Buttons />
|
||||||
<Buttons v-if="!store.loading" />
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ useScreenClick((x, y) => {
|
|||||||
store.scrollProjects("right");
|
store.scrollProjects("right");
|
||||||
} else if (circleContains(BUTTONS.quit.position, [x, y], CLICK_RADIUS)) {
|
} else if (circleContains(BUTTONS.quit.position, [x, y], CLICK_RADIUS)) {
|
||||||
startButtonAnimation("quit");
|
startButtonAnimation("quit");
|
||||||
throw new Error("quit");
|
store.animateOutro();
|
||||||
} else if (
|
} else if (
|
||||||
circleContains(BUTTONS.link.position, [x, y], CLICK_RADIUS) &&
|
circleContains(BUTTONS.link.position, [x, y], CLICK_RADIUS) &&
|
||||||
project?.link
|
project?.link
|
||||||
@@ -102,9 +102,7 @@ useScreenClick((x, y) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
useRender((ctx) => {
|
useRender((ctx) => {
|
||||||
if (!currentAnimation) return;
|
if (currentAnimation?.showButton) {
|
||||||
|
|
||||||
if (currentAnimation.showButton) {
|
|
||||||
const image = BUTTONS[currentAnimation.type].image;
|
const image = BUTTONS[currentAnimation.type].image;
|
||||||
ctx.drawImage(
|
ctx.drawImage(
|
||||||
image!,
|
image!,
|
||||||
@@ -113,7 +111,7 @@ useRender((ctx) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentAnimation.showSmallCircle) {
|
if (currentAnimation?.showSmallCircle) {
|
||||||
ctx.drawImage(
|
ctx.drawImage(
|
||||||
assets.projects.bottomScreen.circleSmall,
|
assets.projects.bottomScreen.circleSmall,
|
||||||
currentAnimation.position[0] - 28,
|
currentAnimation.position[0] - 28,
|
||||||
@@ -121,15 +119,17 @@ useRender((ctx) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentAnimation.showBigCircle) {
|
if (currentAnimation?.showBigCircle) {
|
||||||
ctx.drawImage(
|
ctx.drawImage(
|
||||||
assets.projects.bottomScreen.circleBig,
|
assets.projects.bottomScreen.circleBig,
|
||||||
currentAnimation.position[0] - 44,
|
currentAnimation.position[0] - 44,
|
||||||
currentAnimation.position[1] - 44,
|
currentAnimation.position[1] - 44,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
|
ctx.fillStyle = `rgba(0, 0, 0, ${store.isIntro ? store.intro.fadeOpacity : store.isOutro ? store.outro.fadeOpacity : 0})`;
|
||||||
|
ctx.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||||
|
});
|
||||||
useKeyDown((key) => {
|
useKeyDown((key) => {
|
||||||
if (currentAnimation) return;
|
if (currentAnimation) return;
|
||||||
switch (key) {
|
switch (key) {
|
||||||
|
|||||||
@@ -124,6 +124,9 @@ useRender((ctx) => {
|
|||||||
"black",
|
"black",
|
||||||
"black",
|
"black",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ctx.fillStyle = `rgba(0, 0, 0, ${store.isIntro ? store.intro.fadeOpacity : store.isOutro ? store.outro.fadeOpacity : 0})`;
|
||||||
|
ctx.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||||
});
|
});
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ const store = useProjectsStore();
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<template v-if="!store.loading">
|
||||||
<Background />
|
<Background />
|
||||||
|
<Project />
|
||||||
<Project v-if="!store.loading" />
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -13,6 +13,17 @@ export const useProjectsStore = defineStore("projects", {
|
|||||||
currentProject: 0,
|
currentProject: 0,
|
||||||
loading: true,
|
loading: true,
|
||||||
offsetX: 0,
|
offsetX: 0,
|
||||||
|
|
||||||
|
intro: {
|
||||||
|
fadeOpacity: 1,
|
||||||
|
},
|
||||||
|
|
||||||
|
outro: {
|
||||||
|
fadeOpacity: 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
isIntro: true,
|
||||||
|
isOutro: false,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
@@ -97,5 +108,44 @@ export const useProjectsStore = defineStore("projects", {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
animateIntro() {
|
||||||
|
this.isIntro = true;
|
||||||
|
|
||||||
|
gsap.fromTo(
|
||||||
|
this.intro,
|
||||||
|
{ fadeOpacity: 1 },
|
||||||
|
{
|
||||||
|
delay: 3,
|
||||||
|
fadeOpacity: 0,
|
||||||
|
duration: 0.35,
|
||||||
|
ease: "none",
|
||||||
|
onComplete: () => {
|
||||||
|
this.isIntro = false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
animateOutro() {
|
||||||
|
this.isOutro = true;
|
||||||
|
|
||||||
|
gsap.fromTo(
|
||||||
|
this.outro,
|
||||||
|
{ fadeOpacity: 0 },
|
||||||
|
{
|
||||||
|
delay: 0.5,
|
||||||
|
fadeOpacity: 1,
|
||||||
|
duration: 0.35,
|
||||||
|
ease: "none",
|
||||||
|
onComplete: () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const router = useRouter();
|
||||||
|
router.push({ query: {} });
|
||||||
|
}, 3000);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user