feat(achievements): black fade in and out from home and settings screen

This commit is contained in:
2026-01-26 17:54:13 +01:00
parent 1ec5953c71
commit f453839599
14 changed files with 161 additions and 72 deletions

View File

@@ -2,9 +2,14 @@ import gsap from "gsap";
export const useAchievementsScreen = defineStore("achievementsScreen", {
state: () => ({
fadeToBlack: {
opacity: 0,
active: false,
isOutro: false,
},
intro: {
stage1Opacity: 0,
stage2Opacity: 0,
itemOffsets: {} as Record<number, number>,
progressBar: 0,
},
@@ -12,7 +17,6 @@ export const useAchievementsScreen = defineStore("achievementsScreen", {
outro: {
stage1Opacity: 1,
stage2Opacity: 1,
stage3Opacity: 1,
},
isIntro: true,
@@ -20,6 +24,51 @@ export const useAchievementsScreen = defineStore("achievementsScreen", {
}),
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;
@@ -41,30 +90,20 @@ export const useAchievementsScreen = defineStore("achievementsScreen", {
{ stage1Opacity: 0 },
{
stage1Opacity: 1,
duration: 0.3,
duration: 0.5,
ease: "none",
},
)
.fromTo(
this.intro,
{ stage2Opacity: 0 },
{
stage2Opacity: 1,
duration: 0.5,
ease: "none",
},
0.5,
)
.fromTo(
this.intro,
{ progressBar: 0 },
{
progressBar: 1,
duration: 1.5,
ease: "power2.out",
},
0.25,
);
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(
@@ -85,6 +124,14 @@ export const useAchievementsScreen = defineStore("achievementsScreen", {
gsap
.timeline()
.fromTo(
this.outro,
{ stage1Opacity: 1 },
{
stage1Opacity: 0,
duration: 0.3,
},
)
.fromTo(
this.outro,
{ stage2Opacity: 1 },
@@ -92,28 +139,12 @@ export const useAchievementsScreen = defineStore("achievementsScreen", {
stage2Opacity: 0,
duration: 0.3,
},
)
.fromTo(
this.outro,
{ stage3Opacity: 1 },
{
stage3Opacity: 0,
duration: 0.3,
},
"-=0.15",
)
.fromTo(
this.outro,
{ stage1Opacity: 1 },
{
stage1Opacity: 0,
duration: 0.3,
ease: "none",
},
)
.call(() => {
const app = useAppStore();
app.navigateTo("home");
app.navigateTo(app.previousScreen);
this.animateFadeToBlackOutro();
});
},

View File

@@ -29,6 +29,7 @@ export const useAppStore = defineStore("app", {
return {
booted: false,
settings,
previousScreen: "home" as AppScreen,
screen: "home" as AppScreen,
camera: null as THREE.Camera | null,
};
@@ -40,6 +41,7 @@ export const useAppStore = defineStore("app", {
},
navigateTo(screen: AppScreen) {
this.previousScreen = this.screen;
this.screen = screen;
const achievements = useAchievementsStore();

View File

@@ -1,5 +1,13 @@
import gsap from "gsap";
export type HomeButton =
| "projects"
| "contact"
| "gallery"
| "theme"
| "settings"
| "achievements";
export const useHomeStore = defineStore("home", {
state: () => ({
intro: {
@@ -14,11 +22,25 @@ export const useHomeStore = defineStore("home", {
animateTop: false,
},
selectedButton: "projects" as HomeButton,
isIntro: true,
isOutro: false,
}),
actions: {
reset() {
const app = useAppStore();
if (app.previousScreen === "achievements") {
return;
}
const selectedButton = this.selectedButton;
this.$reset();
this.selectedButton = selectedButton;
this.animateIntro();
},
animateIntro() {
this.isIntro = true;
@@ -52,12 +74,18 @@ export const useHomeStore = defineStore("home", {
},
animateOutro(to: AppScreen) {
if (to === "achievements") {
const achievementsScreen = useAchievementsScreen();
achievementsScreen.animateFadeToBlackIntro();
return;
}
this.isOutro = true;
this.outro.animateTop = to !== "settings";
const timeline = gsap.timeline({
onComplete: () => {
this.isOutro = true;
this.isOutro = false;
const app = useAppStore();
if (to === "gallery") {

View File

@@ -1,8 +1,25 @@
export type SettingsButton =
| "options"
| "optionsLanguage"
| "optionsGbaMode"
| "optionsStartUp"
| "clock"
| "clockAlarm"
| "clockTime"
| "clockDate"
| "user"
| "userBirthday"
| "userUserName"
| "userMessage"
| "userColor"
| "touchScreen";
export const useSettingsStore = defineStore("settings", {
state: () => ({
currentMenu: null as SettingsMenu | null,
currentSubMenu: null as SettingsSubMenu | null,
menuExpanded: false,
selectedButton: "options" as SettingsButton,
}),
actions: {