feat(home): intro + outro animations

This commit is contained in:
2025-11-16 20:19:47 +01:00
parent 458f027cdb
commit 658eb02c23
18 changed files with 2764 additions and 5088 deletions

View File

@@ -1,10 +1,17 @@
<script setup lang="ts">
import gsap from "gsap";
// the out transition:
// clicked button goes up
// other buttons, including selector fade away, text + status bar of upper screen and clock hands fades away 2x faster
// other buttons + calendar + clock body finish fading away at the same time
// then we wait a bit, and new screen starts appearing
import GameButton from "./GameButton.vue";
import PictochatButton from "./PictochatButton.vue";
import DownloadPlayButton from "./DownloadPlayButton.vue";
import Selector from "./Selector.vue";
const store = useHomeStore();
const BUTTONS_CONFIG = {
game: [31, 23, 193, 49],
pictochat: [31, 71, 97, 49],
@@ -13,29 +20,11 @@ const BUTTONS_CONFIG = {
type ButtonType = keyof typeof BUTTONS_CONFIG;
const animationPercentage = ref(0);
const { selectedButton, selectorPosition } = useButtonNavigation({
buttons: BUTTONS_CONFIG,
initialButton: "game",
onButtonClick: (buttonName) => {
if (animationPercentage.value > 0) return;
gsap.fromTo(
animationPercentage,
{ value: 0 },
{
value: 1,
duration: 0.35,
ease: "none",
onComplete: () => {
if (buttonName === "pictochat") {
navigateTo("/contact");
} else {
throw new Error(`Not implemented: ${buttonName}`);
}
},
},
);
onButtonClick: () => {
store.animateOutro();
},
navigation: {
game: {
@@ -56,28 +45,32 @@ const { selectedButton, selectorPosition } = useButtonNavigation({
});
const getButtonOffset = (button: ButtonType) => {
if (selectedButton.value === button) return animationPercentage.value * -200;
if (selectedButton.value === button) return store.outro.buttonOffsetY;
return 0;
};
const getOpacity = () => (1 - animationPercentage.value) * 100;
const getOpacity = (button?: ButtonType) => {
if (store.isIntro) return store.intro.stage1Opacity;
if (selectedButton.value === button) return 1;
return store.outro.stage1Opacity;
};
</script>
<template>
<GameButton
:x="33"
:y="25 + getButtonOffset('game')"
:opacity="getOpacity()"
:opacity="getOpacity('game')"
/>
<DownloadPlayButton
:x="128"
:y="72 + getButtonOffset('downloadPlay')"
:opacity="getOpacity()"
:opacity="getOpacity('downloadPlay')"
/>
<PictochatButton
:x="32"
:y="72 + getButtonOffset('pictochat')"
:opacity="getOpacity()"
:opacity="getOpacity('pictochat')"
/>
<Selector

View File

@@ -10,7 +10,7 @@ const buttonImage = useTemplateRef("buttonImage");
useRender((ctx) => {
if (!buttonImage.value) return;
ctx.globalAlpha = props.opacity / 100;
ctx.globalAlpha = props.opacity;
ctx.drawImage(buttonImage.value, props.x, props.y);
});
</script>

View File

@@ -10,7 +10,7 @@ const buttonImage = useTemplateRef("buttonImage");
useRender((ctx) => {
if (!buttonImage.value) return;
ctx.globalAlpha = props.opacity / 100;
ctx.globalAlpha = props.opacity;
ctx.drawImage(buttonImage.value, props.x, props.y);
});
</script>

View File

@@ -10,7 +10,7 @@ const buttonImage = useTemplateRef("buttonImage");
useRender((ctx) => {
if (!buttonImage.value) return;
ctx.globalAlpha = props.opacity / 100;
ctx.globalAlpha = props.opacity;
ctx.drawImage(buttonImage.value, props.x, props.y);
});
</script>

View File

@@ -46,7 +46,7 @@ useRender((ctx) => {
const w = Math.floor(currentWidth);
const h = Math.floor(currentHeight);
ctx.globalAlpha = props.opacity / 100;
ctx.globalAlpha = props.opacity;
ctx.drawImage(cornerImage.value, x, y);