feat(settings): number input animation
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import gsap from "gsap";
|
||||
|
||||
const APP_COLOR_TO_FONT_COLOR: Record<string, string> = {
|
||||
"#61829a": "#fbfbfb", // cyan
|
||||
"#ba4900": "#fbe3d3", // maroon
|
||||
@@ -78,6 +80,48 @@ const downImage = computed(() => {
|
||||
|
||||
const squareWidth = computed(() => upImage.value.rect.width);
|
||||
|
||||
const SLIDE_OFFSET = 96;
|
||||
const SLIDE_DURATION = 0.25;
|
||||
const ARROW_SLIDE_DELAY = 0.15;
|
||||
const ARROW_SLIDE_DURATION = 0.15;
|
||||
|
||||
const animation = reactive({
|
||||
offsetY: SLIDE_OFFSET,
|
||||
opacity: 0,
|
||||
upArrowOffsetY: ARROW_IMAGE_HEIGHT,
|
||||
downArrowOffsetY: -ARROW_IMAGE_HEIGHT,
|
||||
});
|
||||
|
||||
const animateIntro = async () => {
|
||||
await gsap
|
||||
.timeline()
|
||||
.to(animation, { offsetY: 0, duration: SLIDE_DURATION, ease: "none" }, 0)
|
||||
.to(animation, { opacity: 1, duration: SLIDE_DURATION, ease: "none" }, 0)
|
||||
.to(
|
||||
animation,
|
||||
{ upArrowOffsetY: 0, duration: ARROW_SLIDE_DURATION, ease: "none" },
|
||||
SLIDE_DURATION + ARROW_SLIDE_DELAY,
|
||||
)
|
||||
.to(
|
||||
animation,
|
||||
{ downArrowOffsetY: 0, duration: ARROW_SLIDE_DURATION, ease: "none" },
|
||||
SLIDE_DURATION + ARROW_SLIDE_DELAY,
|
||||
);
|
||||
};
|
||||
|
||||
const animateOutro = async () => {
|
||||
await gsap
|
||||
.timeline()
|
||||
.to(
|
||||
animation,
|
||||
{ offsetY: SLIDE_OFFSET, duration: SLIDE_DURATION, ease: "none" },
|
||||
0,
|
||||
)
|
||||
.to(animation, { opacity: 0, duration: SLIDE_DURATION, ease: "none" }, 0);
|
||||
};
|
||||
|
||||
defineExpose({ animateIntro, animateOutro });
|
||||
|
||||
const increase = () => {
|
||||
const newValue = value.value + 1;
|
||||
value.value = newValue > props.max ? props.min : newValue;
|
||||
@@ -89,8 +133,16 @@ const decrease = () => {
|
||||
};
|
||||
|
||||
onRender((ctx) => {
|
||||
// arrow up
|
||||
upImage.value.draw(ctx, props.x, Y);
|
||||
ctx.globalAlpha = animation.opacity;
|
||||
ctx.translate(0, animation.offsetY);
|
||||
|
||||
// arrow up (clipped to area above the number square)
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.rect(props.x, 0, squareWidth.value, Y + ARROW_IMAGE_HEIGHT);
|
||||
ctx.clip();
|
||||
upImage.value.draw(ctx, props.x, Y + animation.upArrowOffsetY);
|
||||
ctx.restore();
|
||||
|
||||
// outline
|
||||
ctx.fillStyle = "#515151";
|
||||
@@ -123,8 +175,22 @@ onRender((ctx) => {
|
||||
Y + ARROW_IMAGE_HEIGHT + Math.floor((SQUARE_HEIGHT - 39) / 2),
|
||||
);
|
||||
|
||||
// arrow down
|
||||
downImage.value.draw(ctx, props.x, Y + ARROW_IMAGE_HEIGHT + SQUARE_HEIGHT);
|
||||
// arrow down (clipped to area below the number square)
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.rect(
|
||||
props.x,
|
||||
Y + ARROW_IMAGE_HEIGHT + SQUARE_HEIGHT,
|
||||
squareWidth.value,
|
||||
ARROW_IMAGE_HEIGHT,
|
||||
);
|
||||
ctx.clip();
|
||||
downImage.value.draw(
|
||||
ctx,
|
||||
props.x,
|
||||
Y + ARROW_IMAGE_HEIGHT + SQUARE_HEIGHT + animation.downArrowOffsetY,
|
||||
);
|
||||
ctx.restore();
|
||||
|
||||
// title
|
||||
ctx.font = "10px NDS10";
|
||||
|
||||
Reference in New Issue
Block a user