feat(settings/options/startUp): intro and outro animation
@@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { until } from "@vueuse/core";
|
import { until } from "@vueuse/core";
|
||||||
|
import gsap from "gsap";
|
||||||
|
|
||||||
const app = useAppStore();
|
const app = useAppStore();
|
||||||
const store = useSettingsStore();
|
const store = useSettingsStore();
|
||||||
@@ -9,6 +10,63 @@ const { assets } = useAssets();
|
|||||||
const renderingModeAssets =
|
const renderingModeAssets =
|
||||||
assets.images.settings.bottomScreen.options.renderingMode;
|
assets.images.settings.bottomScreen.options.renderingMode;
|
||||||
|
|
||||||
|
const HEADER_HEIGHT = renderingModeAssets.buttonHeader.rect.height;
|
||||||
|
const HEADER_SLIDE_DURATION = 0.2;
|
||||||
|
const BUTTON_STAGGER = 0.3;
|
||||||
|
const SLIDE_OFFSET = 96;
|
||||||
|
const SLIDE_DURATION = 0.25;
|
||||||
|
|
||||||
|
const animation = reactive({
|
||||||
|
_3dMode: { headerOffsetY: HEADER_HEIGHT * 3, opacity: 0 },
|
||||||
|
_2dMode: { headerOffsetY: HEADER_HEIGHT * 3, opacity: 0 },
|
||||||
|
outroOffsetY: 0,
|
||||||
|
outroOpacity: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
const animateIntro = async () => {
|
||||||
|
await gsap
|
||||||
|
.timeline()
|
||||||
|
.to(
|
||||||
|
animation._3dMode,
|
||||||
|
{
|
||||||
|
opacity: 1,
|
||||||
|
headerOffsetY: 0,
|
||||||
|
duration: HEADER_SLIDE_DURATION,
|
||||||
|
ease: "none",
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
.to(
|
||||||
|
animation._2dMode,
|
||||||
|
{
|
||||||
|
opacity: 1,
|
||||||
|
headerOffsetY: 0,
|
||||||
|
duration: HEADER_SLIDE_DURATION,
|
||||||
|
ease: "none",
|
||||||
|
},
|
||||||
|
BUTTON_STAGGER,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const animateOutro = async () => {
|
||||||
|
await gsap
|
||||||
|
.timeline()
|
||||||
|
.to(
|
||||||
|
animation,
|
||||||
|
{ outroOffsetY: SLIDE_OFFSET, duration: SLIDE_DURATION, ease: "none" },
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
.to(
|
||||||
|
animation,
|
||||||
|
{ outroOpacity: 0, duration: SLIDE_DURATION, ease: "none" },
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
animateIntro();
|
||||||
|
});
|
||||||
|
|
||||||
const { selected, selectorPosition } = useButtonNavigation({
|
const { selected, selectorPosition } = useButtonNavigation({
|
||||||
buttons: {
|
buttons: {
|
||||||
_3dMode: [11, 27, 233, 74],
|
_3dMode: [11, 27, 233, 74],
|
||||||
@@ -25,7 +83,8 @@ const { selected, selectorPosition } = useButtonNavigation({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = async () => {
|
||||||
|
await animateOutro();
|
||||||
store.closeSubMenu();
|
store.closeSubMenu();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -39,7 +98,8 @@ const handleConfirm = () => {
|
|||||||
mode === "3d"
|
mode === "3d"
|
||||||
? $t("settings.options.startUp.confirmation3d")
|
? $t("settings.options.startUp.confirmation3d")
|
||||||
: $t("settings.options.startUp.confirmation2d"),
|
: $t("settings.options.startUp.confirmation2d"),
|
||||||
onClosed: () => {
|
onClosed: async () => {
|
||||||
|
await animateOutro();
|
||||||
store.closeSubMenu();
|
store.closeSubMenu();
|
||||||
},
|
},
|
||||||
timeout: 2000,
|
timeout: 2000,
|
||||||
@@ -62,25 +122,35 @@ onRender((ctx) => {
|
|||||||
logo: AtlasImage,
|
logo: AtlasImage,
|
||||||
y: number,
|
y: number,
|
||||||
active: boolean,
|
active: boolean,
|
||||||
|
key: "_3dMode" | "_2dMode",
|
||||||
) => {
|
) => {
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.translate(16, y);
|
ctx.translate(16, y + animation.outroOffsetY);
|
||||||
|
|
||||||
if (active) {
|
const buttonWidth = renderingModeAssets.buttonBody.rect.width;
|
||||||
renderingModeAssets.buttonActive.draw(ctx, 0, 0, { colored: true });
|
|
||||||
} else {
|
|
||||||
renderingModeAssets.button.draw(ctx, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
const buttonWidth = renderingModeAssets.button.rect.width;
|
const bodyImg = active
|
||||||
|
? renderingModeAssets.buttonActiveBody
|
||||||
|
: renderingModeAssets.buttonBody;
|
||||||
|
const headerImg = active
|
||||||
|
? renderingModeAssets.buttonActiveHeader
|
||||||
|
: renderingModeAssets.buttonHeader;
|
||||||
|
const colorOpts = active ? { colored: true } : undefined;
|
||||||
|
|
||||||
ctx.fillStyle = "#000000";
|
ctx.globalAlpha = animation[key].opacity * animation.outroOpacity;
|
||||||
fillImageTextHCentered(ctx, logo, title, 0, 4, buttonWidth, 4);
|
|
||||||
|
|
||||||
|
bodyImg.draw(ctx, 0, HEADER_HEIGHT - 2, colorOpts);
|
||||||
ctx.fillStyle = "#282828";
|
ctx.fillStyle = "#282828";
|
||||||
const text = $t("settings.options.startUp.autoStart");
|
const text = $t("settings.options.startUp.autoStart");
|
||||||
fillTextHCenteredMultiline(ctx, text, 0, y, buttonWidth, 15);
|
fillTextHCenteredMultiline(ctx, text, 0, y, buttonWidth, 15);
|
||||||
|
|
||||||
|
ctx.translate(0, animation[key].headerOffsetY);
|
||||||
|
headerImg.draw(ctx, 0, 0, colorOpts);
|
||||||
|
ctx.fillStyle = "#000000";
|
||||||
|
fillImageTextHCentered(ctx, logo, title, 0, 4, buttonWidth, 4);
|
||||||
|
|
||||||
|
ctx.globalAlpha = 1;
|
||||||
|
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -89,12 +159,14 @@ onRender((ctx) => {
|
|||||||
renderingModeAssets._3dMode,
|
renderingModeAssets._3dMode,
|
||||||
32,
|
32,
|
||||||
selected.value === "_3dMode",
|
selected.value === "_3dMode",
|
||||||
|
"_3dMode",
|
||||||
);
|
);
|
||||||
drawButton(
|
drawButton(
|
||||||
$t("settings.options.startUp.2dMode"),
|
$t("settings.options.startUp.2dMode"),
|
||||||
renderingModeAssets._2dMode,
|
renderingModeAssets._2dMode,
|
||||||
96,
|
96,
|
||||||
selected.value === "_2dMode",
|
selected.value === "_2dMode",
|
||||||
|
"_2dMode",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@@ -108,5 +180,13 @@ onRender((ctx) => {
|
|||||||
@activate-a="handleConfirm"
|
@activate-a="handleConfirm"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<CommonButtonSelector :rect="selectorPosition" />
|
<CommonButtonSelector
|
||||||
|
:rect="[
|
||||||
|
selectorPosition[0],
|
||||||
|
selectorPosition[1] + animation.outroOffsetY,
|
||||||
|
selectorPosition[2],
|
||||||
|
selectorPosition[3],
|
||||||
|
]"
|
||||||
|
:opacity="animation[selected].opacity * animation.outroOpacity"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
|
After Width: | Height: | Size: 796 B |
|
After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 130 B |
|
After Width: | Height: | Size: 188 B |
|
Before Width: | Height: | Size: 168 B |
|
Before Width: | Height: | Size: 88 B |