UNPKG

zrender

Version:

A lightweight graphic library providing 2d draw for Apache ECharts

142 lines (110 loc) 3.66 kB
/** * 动画主控制器 * @config target 动画对象,可以是数组,如果是数组的话会批量分发onframe等事件 * @config life(1000) 动画时长 * @config delay(0) 动画延迟时间 * @config loop(true) * @config onframe * @config easing(optional) * @config ondestroy(optional) * @config onrestart(optional) * * TODO pause */ import easingFuncs, {AnimationEasing} from './easing'; import type Animation from './Animation'; import { isFunction, noop } from '../core/util'; import { createCubicEasingFunc } from './cubicEasing'; type OnframeCallback = (percent: number) => void; type ondestroyCallback = () => void type onrestartCallback = () => void export type DeferredEventTypes = 'destroy' | 'restart' // type DeferredEventKeys = 'ondestroy' | 'onrestart' export interface ClipProps { life?: number delay?: number loop?: boolean easing?: AnimationEasing onframe?: OnframeCallback ondestroy?: ondestroyCallback onrestart?: onrestartCallback } export default class Clip { private _life: number private _delay: number private _inited: boolean = false private _startTime = 0 // 开始时间单位毫秒 private _pausedTime = 0 private _paused = false animation: Animation loop: boolean easing: AnimationEasing easingFunc: (p: number) => number // For linked list. Readonly next: Clip prev: Clip onframe: OnframeCallback ondestroy: ondestroyCallback onrestart: onrestartCallback constructor(opts: ClipProps) { this._life = opts.life || 1000; this._delay = opts.delay || 0; this.loop = opts.loop || false; this.onframe = opts.onframe || noop; this.ondestroy = opts.ondestroy || noop; this.onrestart = opts.onrestart || noop; opts.easing && this.setEasing(opts.easing); } step(globalTime: number, deltaTime: number): boolean { // Set startTime on first step, or _startTime may has milleseconds different between clips // PENDING if (!this._inited) { this._startTime = globalTime + this._delay; this._inited = true; } if (this._paused) { this._pausedTime += deltaTime; return; } const life = this._life; let elapsedTime = globalTime - this._startTime - this._pausedTime; let percent = elapsedTime / life; // PENDING: Not begin yet. Still run the loop. // In the case callback needs to be invoked. // Or want to update to the begin state at next frame when `setToFinal` and `delay` are both used. // To avoid the unexpected blink. if (percent < 0) { percent = 0; } percent = Math.min(percent, 1); const easingFunc = this.easingFunc; const schedule = easingFunc ? easingFunc(percent) : percent; this.onframe(schedule); // 结束 if (percent === 1) { if (this.loop) { // Restart const remainder = elapsedTime % life; this._startTime = globalTime - remainder; this._pausedTime = 0; this.onrestart(); } else { return true; } } return false; } pause() { this._paused = true; } resume() { this._paused = false; } setEasing(easing: AnimationEasing) { this.easing = easing; this.easingFunc = isFunction(easing) ? easing : easingFuncs[easing] || createCubicEasingFunc(easing); } }