Blame view

node_modules/zrender/src/animation/Clip.ts 3.57 KB
bd028579   易尊强   2/28
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
  /**
   * 动画主控制器
   * @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);
      }
  }