UNPKG

@visactor/vrender-animate

Version:

This module provides a graph-based animation system for VRender.

97 lines (92 loc) 3.78 kB
import { Generator } from "@visactor/vrender-core/common/generator"; import { AnimateStatus } from "@visactor/vrender-core/event/constant"; import { EventEmitter } from "@visactor/vutils"; export class DefaultTimeline extends EventEmitter { get animateCount() { return this._animateCount; } constructor() { super(), this.head = null, this.tail = null, this.animateMap = new Map, this._animateCount = 0, this._playSpeed = 1, this._totalDuration = 0, this._startTime = 0, this._currentTime = 0, this._animationEndFlag = !0, this.id = Generator.GenAutoIncrementId(), this.paused = !1; } isRunning() { return !this.paused && this._animateCount > 0; } forEachAccessAnimate(cb) { let current = this.head, index = 0; for (;current; ) { const next = current.next; cb(current.animate, index), index++, current = next; } } addAnimate(animate) { const newNode = { animate: animate, next: null, prev: null }; this.head ? this.tail && (this.tail.next = newNode, newNode.prev = this.tail, this.tail = newNode) : (this.head = newNode, this.tail = newNode), this.animateMap.set(animate, newNode), this._animateCount++, this._totalDuration = Math.max(this._totalDuration, animate.getStartTime() + animate.getDuration()); } pause() { this.paused = !0; } resume() { this.paused = !1; } tick(delta) { if (this.paused) return; this._animationEndFlag && (this._animationEndFlag = !1, this.emit("animationStart")); const scaledDelta = delta * this._playSpeed; this._currentTime += scaledDelta, this.forEachAccessAnimate(((animate, i) => { animate.status === AnimateStatus.END ? this.removeAnimate(animate, !0) : animate.status !== AnimateStatus.RUNNING && animate.status !== AnimateStatus.INITIAL || animate.advance(scaledDelta); })), 0 === this._animateCount && (this._animationEndFlag = !0, this.emit("animationEnd")); } clear() { this.forEachAccessAnimate((animate => { animate.release(); })), this.head = null, this.tail = null, this.animateMap.clear(), this._animateCount = 0, this._totalDuration = 0; } removeAnimate(animate, release = !0) { const node = this.animateMap.get(animate); node && (release && (animate._onRemove && animate._onRemove.forEach((cb => cb())), animate.release()), node.prev ? node.prev.next = node.next : this.head = node.next, node.next ? node.next.prev = node.prev : this.tail = node.prev, this.animateMap.delete(animate), this._animateCount--, animate.getStartTime() + animate.getDuration() >= this._totalDuration && this.recalculateTotalDuration()); } recalculateTotalDuration() { this._totalDuration = 0, this.forEachAccessAnimate((animate => { this._totalDuration = Math.max(this._totalDuration, animate.getStartTime() + animate.getDuration()); })); } getTotalDuration() { return this._totalDuration; } getPlaySpeed() { return this._playSpeed; } setPlaySpeed(speed) { this._playSpeed = speed; } getPlayState() { return this.paused ? "paused" : 0 === this.animateCount ? "stopped" : "playing"; } setStartTime(time) { this._startTime = time; } getStartTime() { return this._startTime; } getCurrentTime() { return this._currentTime; } setCurrentTime(time) { this._currentTime = time; } } export const defaultTimeline = new DefaultTimeline; defaultTimeline.isGlobal = !0; //# sourceMappingURL=timeline.js.map