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

165 lines
3.4 KiB
TypeScript

import gsap from "gsap";
export const ACHIEVEMENTS_LINE_HEIGHT = 14;
export const ACHIEVEMENTS_HEADER_Y = 20;
export const ACHIEVEMENTS_LIST_START_Y = ACHIEVEMENTS_HEADER_Y + 55;
export const ACHIEVEMENTS_BOTTOM_START_Y = 10;
export const ACHIEVEMENTS_TOP_SCREEN_COUNT = Math.floor(
(LOGICAL_HEIGHT - ACHIEVEMENTS_LIST_START_Y) / ACHIEVEMENTS_LINE_HEIGHT,
);
export const ACHIEVEMENTS_X = 55;
export const useAchievementsScreen = defineStore("achievementsScreen", {
state: () => ({
fadeToBlack: {
opacity: 0,
active: false,
isOutro: false,
},
intro: {
stage1Opacity: 0,
itemOffsets: {} as Record<number, number>,
progressBar: 0,
},
outro: {
stage1Opacity: 1,
stage2Opacity: 1,
},
isIntro: true,
isOutro: false,
}),
actions: {
animateFadeToBlackIntro() {
this.fadeToBlack.active = true;
this.fadeToBlack.isOutro = false;
gsap
.timeline({
onComplete: () => {
const app = useAppStore();
app.navigateTo("achievements");
},
})
.fromTo(
this.fadeToBlack,
{ opacity: 0 },
{
opacity: 1,
duration: 0.4,
ease: "none",
},
);
},
animateFadeToBlackOutro() {
this.fadeToBlack.active = true;
this.fadeToBlack.isOutro = true;
this.fadeToBlack.opacity = 1;
gsap
.timeline({
onComplete: () => {
this.fadeToBlack.active = false;
this.isOutro = false;
},
})
.fromTo(
this.fadeToBlack,
{ opacity: 1 },
{
opacity: 0,
duration: 0.4,
ease: "none",
},
);
},
animateIntro() {
this.isIntro = true;
this.isOutro = false;
const itemCount = ACHIEVEMENTS.length;
for (let i = 0; i < itemCount; i++) {
this.intro.itemOffsets[i] = -ACHIEVEMENTS_LINE_HEIGHT;
}
const tl = gsap.timeline({
onComplete: () => {
this.isIntro = false;
},
});
tl.fromTo(
this.intro,
{ stage1Opacity: 0 },
{
stage1Opacity: 1,
duration: 0.5,
ease: "none",
},
0.5,
).fromTo(
this.intro,
{ progressBar: 0 },
{
progressBar: 1,
duration: 1.5,
ease: "power2.out",
},
0.25,
);
for (let i = 0; i < itemCount; i++) {
tl.to(
this.intro.itemOffsets,
{
[i]: 0,
duration: 0.4,
ease: "power2.out",
},
0.75 + i * 0.05,
);
}
},
animateOutro() {
this.isIntro = false;
this.isOutro = true;
gsap
.timeline()
.fromTo(
this.outro,
{ stage1Opacity: 1 },
{
stage1Opacity: 0,
duration: 0.3,
},
)
.fromTo(
this.outro,
{ stage2Opacity: 1 },
{
stage2Opacity: 0,
duration: 0.3,
},
"-=0.15",
)
.call(() => {
const app = useAppStore();
app.navigateTo(app.previousScreen);
this.animateFadeToBlackOutro();
});
},
getItemOffset(index: number): number {
return this.intro.itemOffsets[index] ?? 0;
},
},
});