feat(stage-ui): refactor animators in poppin'text into creator pattern; rainbow text
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { FieldRange } from '@proj-airi/ui'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import PoppinText from './PoppinText.web.vue'
|
||||
|
||||
import { fadeAnimator, popupAnimator } from './animators'
|
||||
import { createFadeAnimator, createFloatAnimator, createPopupAnimator } from './animators'
|
||||
|
||||
const text = ref('キラキラドキドキキラキラドキドキキラキラドキドキキラキラドキドキ')
|
||||
const text = ref('行こう、七色のキラキラドキドキに向かって!')
|
||||
const duration = ref(750)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -15,7 +17,13 @@ const text = ref('キラキラドキドキキラキラドキドキキラキラ
|
||||
:layout="{ type: 'grid', width: '100%' }"
|
||||
>
|
||||
<template #controls>
|
||||
<ThemeColorsHueControl />
|
||||
<FieldRange
|
||||
v-model.number="duration"
|
||||
:min="50"
|
||||
:max="3000"
|
||||
:step="50"
|
||||
label="Duration"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<Variant
|
||||
@@ -23,7 +31,7 @@ const text = ref('キラキラドキドキキラキラドキドキキラキラ
|
||||
title="Popup"
|
||||
>
|
||||
<div h-auto w-full p-4>
|
||||
<PoppinText :text="text" :animator="popupAnimator" />
|
||||
<PoppinText :text="text" :animator="createPopupAnimator({ duration })" />
|
||||
</div>
|
||||
</Variant>
|
||||
|
||||
@@ -32,7 +40,16 @@ const text = ref('キラキラドキドキキラキラドキドキキラキラ
|
||||
title="Fade"
|
||||
>
|
||||
<div h-auto w-full p-4>
|
||||
<PoppinText :text="text" :animator="fadeAnimator" />
|
||||
<PoppinText :text="text" :animator="createFadeAnimator({ duration })" />
|
||||
</div>
|
||||
</Variant>
|
||||
|
||||
<Variant
|
||||
id="float"
|
||||
title="Float"
|
||||
>
|
||||
<div h-auto w-full p-4>
|
||||
<PoppinText :text="text" :animator="createFloatAnimator({ duration })" />
|
||||
</div>
|
||||
</Variant>
|
||||
</Story>
|
||||
|
||||
@@ -26,12 +26,13 @@ watch([graphemeClusters, () => props.animator], ([_, animator]) => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="relative overflow-hidden whitespace-nowrap">
|
||||
<div class="relative overflow-hidden whitespace-nowrap text-2xl font-bold font-m-plus-rounded">
|
||||
<span
|
||||
v-for="(cluster, index) in graphemeClusters"
|
||||
:key="index"
|
||||
ref="elements"
|
||||
class="inline-block"
|
||||
class="inline-block color-primary-400"
|
||||
:style="{ '--chromatic-hue': index * 360 / graphemeClusters.length }"
|
||||
>
|
||||
{{ cluster }}
|
||||
</span>
|
||||
|
||||
@@ -1,20 +1,26 @@
|
||||
import type { Animator } from '.'
|
||||
import type { Animator, CreateAnimatorOptions } from '.'
|
||||
|
||||
import { createTimeline } from 'animejs'
|
||||
|
||||
export const fadeAnimator: Animator = (elements: HTMLElement[]) => {
|
||||
const timeline = createTimeline({ loop: true })
|
||||
.set(elements, {
|
||||
opacity: 0,
|
||||
})
|
||||
.add(elements, {
|
||||
opacity: [0, 1],
|
||||
easing: 'easeInOutQuad',
|
||||
duration: 2250,
|
||||
delay: (_, i) => 150 * (i + 1),
|
||||
})
|
||||
export function createFadeAnimator(options: CreateAnimatorOptions): Animator {
|
||||
return (elements: HTMLElement[]) => {
|
||||
if (elements.length === 0) {
|
||||
// NO DIV0
|
||||
return () => {}
|
||||
}
|
||||
|
||||
return () => {
|
||||
timeline.remove(elements)
|
||||
const timeline = createTimeline({ loop: true })
|
||||
.set(elements, {
|
||||
opacity: 0,
|
||||
})
|
||||
.add(elements, {
|
||||
opacity: [0, 1],
|
||||
...options,
|
||||
delay: (_, i) => options.duration / elements.length * (i + 1),
|
||||
})
|
||||
|
||||
return () => {
|
||||
timeline.remove(elements)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import type { Animator, CreateAnimatorOptions } from '.'
|
||||
|
||||
import { createTimeline } from 'animejs'
|
||||
|
||||
export function createFloatAnimator(options: CreateAnimatorOptions): Animator {
|
||||
return (elements: HTMLElement[]) => {
|
||||
if (elements.length === 0) {
|
||||
// NO DIV0
|
||||
return () => {}
|
||||
}
|
||||
|
||||
const timeline = createTimeline({ loop: true })
|
||||
.set(elements, {
|
||||
opacity: 0,
|
||||
translateX: '0.55em',
|
||||
translateY: '1.1em',
|
||||
rotateZ: 180,
|
||||
translateZ: 0,
|
||||
})
|
||||
.add(elements, {
|
||||
opacity: [0, 1],
|
||||
translateY: ['1.1em', 0],
|
||||
translateX: ['0.55em', 0],
|
||||
translateZ: 0,
|
||||
rotateZ: [180, 0],
|
||||
...options,
|
||||
delay: (_, i) => options.duration / elements.length * i,
|
||||
})
|
||||
|
||||
return () => {
|
||||
timeline.remove(elements)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,12 @@
|
||||
import type { EasingParam } from 'animejs'
|
||||
|
||||
export interface CreateAnimatorOptions {
|
||||
duration: number
|
||||
ease?: EasingParam
|
||||
}
|
||||
|
||||
export type Animator = (elements: HTMLElement[]) => (() => void)
|
||||
|
||||
export * from './fade'
|
||||
export * from './float'
|
||||
export * from './popup'
|
||||
|
||||
@@ -1,23 +1,30 @@
|
||||
import type { Animator } from '.'
|
||||
import type { Animator, CreateAnimatorOptions } from '.'
|
||||
|
||||
import { createTimeline } from 'animejs'
|
||||
|
||||
export const popupAnimator: Animator = (elements: HTMLElement[]) => {
|
||||
const timeline = createTimeline({ loop: true })
|
||||
.set(elements, {
|
||||
opacity: 0,
|
||||
translateY: '1.1em',
|
||||
translateZ: 0,
|
||||
})
|
||||
.add(elements, {
|
||||
opacity: [0, 1],
|
||||
translateY: ['1.1em', 0],
|
||||
translateZ: 0,
|
||||
duration: 750,
|
||||
delay: (_, i) => 50 * i,
|
||||
})
|
||||
export function createPopupAnimator(options: CreateAnimatorOptions): Animator {
|
||||
return (elements: HTMLElement[]) => {
|
||||
if (elements.length === 0) {
|
||||
// NO DIV0
|
||||
return () => {}
|
||||
}
|
||||
|
||||
return () => {
|
||||
timeline.remove(elements)
|
||||
const timeline = createTimeline({ loop: true })
|
||||
.set(elements, {
|
||||
opacity: 0,
|
||||
translateY: '1.1em',
|
||||
translateZ: 0,
|
||||
})
|
||||
.add(elements, {
|
||||
opacity: [0, 1],
|
||||
translateY: ['1.1em', 0],
|
||||
translateZ: 0,
|
||||
...options,
|
||||
delay: (_, i) => options.duration / elements.length * i,
|
||||
})
|
||||
|
||||
return () => {
|
||||
timeline.remove(elements)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user