pages235/renderer/viewer/lib/animationController.ts

85 lines
2 KiB
TypeScript

import * as tweenJs from '@tweenjs/tween.js'
export class AnimationController {
private currentAnimation: tweenJs.Group | null = null
private isAnimating = false
private cancelRequested = false
private completionCallbacks: Array<() => void> = []
private currentCancelCallback: (() => void) | null = null
/** Main method */
async startAnimation (createAnimation: () => tweenJs.Group, onCancelled?: () => void): Promise<void> {
if (this.isAnimating) {
await this.cancelCurrentAnimation()
}
return new Promise((resolve) => {
this.isAnimating = true
this.cancelRequested = false
this.currentCancelCallback = onCancelled ?? null
this.currentAnimation = createAnimation()
this.completionCallbacks.push(() => {
this.isAnimating = false
this.currentAnimation = null
resolve()
})
})
}
/** Main method */
async cancelCurrentAnimation (): Promise<void> {
if (!this.isAnimating) return
if (this.currentCancelCallback) {
const callback = this.currentCancelCallback
this.currentCancelCallback = null
callback()
}
return new Promise((resolve) => {
this.cancelRequested = true
this.completionCallbacks.push(() => {
resolve()
})
})
}
animationCycleFinish () {
if (this.cancelRequested) this.forceFinish()
}
forceFinish (callComplete = true) {
if (!this.isAnimating) return
if (this.currentAnimation) {
for (const tween of this.currentAnimation.getAll()) tween.stop()
this.currentAnimation.removeAll()
this.currentAnimation = null
}
this.isAnimating = false
this.cancelRequested = false
const callbacks = [...this.completionCallbacks]
this.completionCallbacks = []
if (callComplete) {
for (const cb of callbacks) cb()
}
}
/** Required method */
update () {
if (this.currentAnimation) {
this.currentAnimation.update()
}
}
get isActive () {
return this.isAnimating
}
get shouldCancel () {
return this.cancelRequested
}
}