feat(settings): intro and outro animation
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
const { onRender } = useScreen();
|
||||
|
||||
const store = useSettingsStore();
|
||||
const { assets } = useAssets();
|
||||
|
||||
onRender((ctx) => {
|
||||
ctx.fillStyle = "black";
|
||||
ctx.font = "7px NDS7";
|
||||
|
||||
ctx.translate(0, -16);
|
||||
ctx.translate(0, -16 + store.notificationYOffset / 3);
|
||||
|
||||
const CALENDAR_COLS = 7;
|
||||
const CALENDAR_ROWS = 5;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
const { onRender } = useScreen();
|
||||
|
||||
const app = useAppStore();
|
||||
const store = useSettingsStore();
|
||||
const { assets } = useAssets();
|
||||
|
||||
const CENTER_X = 63;
|
||||
@@ -53,7 +54,7 @@ function drawLine(
|
||||
}
|
||||
|
||||
onRender((ctx) => {
|
||||
ctx.translate(0, -16);
|
||||
ctx.translate(0, -16 + store.notificationYOffset / 3);
|
||||
|
||||
assets.images.home.topScreen.clock.draw(ctx, 13, 45);
|
||||
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
const { onRender } = useScreen();
|
||||
import gsap from "gsap";
|
||||
|
||||
const { onRender } = useScreen();
|
||||
const store = useSettingsStore();
|
||||
const { assets } = useAssets();
|
||||
|
||||
type NotificationData = {
|
||||
image: AtlasImage;
|
||||
title: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
const menuYOffset = ref(0);
|
||||
const submenuYOffset = ref(0);
|
||||
const visibleMenuNotification = ref<NotificationData | null>(null);
|
||||
const visibleSubmenuNotification = ref<NotificationData | null>(null);
|
||||
|
||||
const renderNotification = (
|
||||
ctx: CanvasRenderingContext2D,
|
||||
image: AtlasImage,
|
||||
@@ -83,13 +95,62 @@ const submenuNotification = computed(() => {
|
||||
};
|
||||
});
|
||||
|
||||
const animateNotification = (
|
||||
curr: NotificationData | null,
|
||||
prev: NotificationData | null,
|
||||
visibleRef: Ref<NotificationData | null>,
|
||||
offsetRef: Ref<number>,
|
||||
) => {
|
||||
if (prev !== null && curr === null) {
|
||||
// slide down
|
||||
visibleRef.value = prev;
|
||||
gsap.fromTo(
|
||||
offsetRef,
|
||||
{ value: 0 },
|
||||
{
|
||||
value: 48,
|
||||
duration: 0.2,
|
||||
ease: "none",
|
||||
onComplete: () => {
|
||||
visibleRef.value = null;
|
||||
},
|
||||
},
|
||||
);
|
||||
} else if (prev === null && curr !== null) {
|
||||
// slide up
|
||||
visibleRef.value = curr;
|
||||
gsap.fromTo(
|
||||
offsetRef,
|
||||
{ value: 48 },
|
||||
{ value: 0, duration: 0.2, ease: "none" },
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
watch(menuNotification, (curr, prev) => {
|
||||
animateNotification(curr, prev, visibleMenuNotification, menuYOffset);
|
||||
});
|
||||
|
||||
watch(submenuNotification, (curr, prev) => {
|
||||
animateNotification(curr, prev, visibleSubmenuNotification, submenuYOffset);
|
||||
});
|
||||
|
||||
onRender((ctx) => {
|
||||
let count = 1;
|
||||
if (menuNotification.value) count++;
|
||||
if (submenuNotification.value) count++;
|
||||
|
||||
ctx.translate(0, 144 - (count - 1) * 16);
|
||||
const submenuY = 144 + submenuYOffset.value;
|
||||
const menuY = visibleSubmenuNotification.value
|
||||
? Math.min(144, submenuY - 16) + menuYOffset.value
|
||||
: 144 + menuYOffset.value;
|
||||
const nextY = visibleMenuNotification.value
|
||||
? menuY
|
||||
: visibleSubmenuNotification.value
|
||||
? submenuY
|
||||
: null;
|
||||
const mainY =
|
||||
nextY !== null
|
||||
? Math.min(144, nextY - 16) + store.notificationYOffset
|
||||
: 144 + store.notificationYOffset;
|
||||
|
||||
ctx.translate(0, mainY);
|
||||
renderNotification(
|
||||
ctx,
|
||||
mainNotification.value.image,
|
||||
@@ -97,23 +158,24 @@ onRender((ctx) => {
|
||||
mainNotification.value.description,
|
||||
);
|
||||
|
||||
if (menuNotification.value) {
|
||||
ctx.translate(0, 16);
|
||||
if (visibleMenuNotification.value) {
|
||||
ctx.translate(0, menuY - mainY);
|
||||
renderNotification(
|
||||
ctx,
|
||||
menuNotification.value.image,
|
||||
menuNotification.value.title,
|
||||
menuNotification.value.description,
|
||||
visibleMenuNotification.value.image,
|
||||
visibleMenuNotification.value.title,
|
||||
visibleMenuNotification.value.description,
|
||||
);
|
||||
}
|
||||
|
||||
if (submenuNotification.value) {
|
||||
ctx.translate(0, 16);
|
||||
if (visibleSubmenuNotification.value) {
|
||||
const prevY = visibleMenuNotification.value ? menuY : mainY;
|
||||
ctx.translate(0, submenuY - prevY);
|
||||
renderNotification(
|
||||
ctx,
|
||||
submenuNotification.value.image,
|
||||
submenuNotification.value.title,
|
||||
submenuNotification.value.description,
|
||||
visibleSubmenuNotification.value.image,
|
||||
visibleSubmenuNotification.value.title,
|
||||
visibleSubmenuNotification.value.description,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -4,6 +4,12 @@ import Calendar from "./Calendar.vue";
|
||||
import Clock from "./Clock.vue";
|
||||
import StatusBar from "./StatusBar.vue";
|
||||
import Notifications from "./Notifications.vue";
|
||||
|
||||
const store = useSettingsStore();
|
||||
|
||||
onMounted(() => {
|
||||
store.animateIntro();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
Reference in New Issue
Block a user