/
animate.ts
78 lines (70 loc) · 2.42 KB
/
animate.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import * as PIXI from 'pixi.js'
import gsap, { Sine } from 'gsap'
import { ComputedRef, watch } from 'vue'
import { removeFrom } from '@/utils/ArrayUtil'
const tween = (
o: PIXI.DisplayObject,
vars: PixiPlugin.Vars,
duration: number,
ease?: gsap.EaseFunction
): gsap.core.Tween => {
return gsap.to(o, { pixi: vars, duration, ease: ease ?? Sine.easeOut })
}
/**
* PIXI.DisplayObjectに対してTweenアニメーションを実行します。
* awaitアニメーション完了を待つことができます。
*/
export const animate = async (...params: Parameters<typeof tween>): Promise<void> => {
await tween(...params)
}
/**
* キャンセル可能なアニメーションを管理・実行します
*/
export class Animator {
private isCancelled = false
private canceller?: ComputedRef<boolean>
private runningTweens: gsap.core.Tween[] = []
/**
* キャンセル可能なアニメーションの管理インスタンスを作成します。
* @param canceller キャンセルすべきかどうかを返すcomputedプロパティ。一度でもtrueになるとその時点で実行中のアニメーションを中断し、以後のアニメーションを全て無視します。
*/
constructor(canceller?: ComputedRef<boolean>) {
this.canceller = canceller
if (canceller) {
const unwatch = watch([this.canceller], val => {
if (!val) {
return
}
this.isCancelled = true
unwatch()
if (this.runningTweens.length) {
this.runningTweens.forEach(tw => tw.kill())
this.runningTweens.length = 0
}
})
}
}
/**
* アニメーションを実行します。すでにキャンセルされている場合には何も起こりません。
* また、実行を開始した後でキャンセルが成立した場合、アニメーションは途中で打ち切られます。
* 実行されなかった場合及び、実行が打ち切られた場合にもPromiseはresolveになります(rejectはされません)。
*/
async animate(...params: Parameters<typeof animate>) {
if (!this.alive) {
return
}
const tw = tween(...params)
this.runningTweens.push(tw)
await tw
removeFrom(this.runningTweens, tw)
}
set(o: PIXI.DisplayObject, vars: PixiPlugin.Vars) {
this.alive && gsap.set(o, vars)
}
cancel() {
this.isCancelled = true
}
get alive() {
return !this.isCancelled
}
}