这个变革值,就相便是我们 CSS animation 中的 linear 动画曲线。这动画曲线就是一条直线。这里我们先用这个实现我们的 Animation 类,就先不去处理惩罚我们的 timingFunction,后头我们再去处理惩罚这个动态的动画曲线。
有了这个变革值,我们就可以用 startValue(初始值)+ 变革值,获得当前进度对应的属性值。我们的代码就是这样实现的:
run(time) { let range = this.endValue - this.startValue; this.object[this.property] = this.startValue + (range * time) / this.duration; }
这样 Animation 就可以运作的了。接下来我们把这个 Animation 添加到 Timeline 的 animation 行列内里,让它在行列中被执行。
我们上面说到,这个 Animation 中的 run 要领吸收的 time(时间)是一个虚拟的时间。所以在 Timeline 中挪用这个 run 要领的时候就要把一个虚拟时间传给 Animation,这样我们的动画就可以运作了。
好,这里我们要添加 animation 到 timeline 内里,首先我们就要有一个 animations 行列。这个我们就直接生成一个 animations Set。
这个与其他 Timeline 中的储存方法一样,我们成立一个全局的 ANIMATIONS 常量来储存,它的值就用 Symbol 包裹起来。这样就可以制止这个行列不小心被外部挪用到了。
const ANIMATIONS = Symbol('animations');
这个行列还需要在 Timeline 类结构的时候,就赋值一个空的 Set。
constructor() { this[ANIMATIONS] = new Set(); }
有行列,那么我们一定就需要有一个插手行列的要领,所以我们在 Timeline 类中还要插手一个 add() 要领。实现逻辑如下:
constructor() { this[ANIMATIONS] = new Set(); }
我们要在 Timeline 中给 Animation 的 run 传一个当前已经执行了的时长。要计较这个时长的话,就要在 Timeline 开始的时候就记录好一个开始时间。然后每一个动画被触发的时候,用 当前时间 - Timeline 开始时间 才气获恰当前已经运行了多久。
可是之前的 tick 是写在了 constructor 内里,Timeline 开始时间一定是放在 start 要领之中,所觉得了可以或许更利便的可以得到这个时间,我们可以直接把 tick 声明放到 start 内里。
固然说这个窜改会让我们每次 Timeline 启动的时候,城市从头构建一个 tick 工具函数。可是这种要了解更便于快速实现这个成果,不外想要机能更好的同学也是可以优化这一个处所的。
移动完我们 tick 之后,我们就可以在 tick 内里插手挪用 ANIMATIONS 行列的 animation(动画)了。因为一个 Timeline 内里可以有多个animation,而且每一帧城市敦促他们到下一个进度的属性状态。所以这里我们就用一个轮回,然后挪用一遍我们 ANIMATIONS 行列内里的所有的 animation 的 run 要领。
最后我们的代码就是这样的:
const TICK = Symbol('tick'); const TICK_HANDLER = Symbol('tick-handler'); const ANIMATIONS = Symbol('animations'); export class Timeline { constructor() { this[ANIMATIONS] = new Set(); } start() { let startTime = Date.now(); this[TICK] = () => { let t = Date.now() - startTime; for (let animation of this[ANIMATIONS]) { animation.run(t); } requestAnimationFrame(this[TICK]); }; this[TICK](); } pause() {} resume() {} reset() {} add(animation) { this[ANIMATIONS].add(animation); } } export class Animation { constructor(object, property, startValue, endValue, duration, timingFunction) { this.object = object; this.property = property; this.startValue = startValue; this.endValue = endValue; this.duration = duration; this.timingFunction = timingFunction; } run(time) { console.log(time); let range = this.endValue - this.startValue; this.object[this.property] = this.startValue + (range * time) / this.duration; } }
我们在 animation 的 run 要领中,插手一个 console.log(time),利便我们调试。
最后我们在 main.js 中,把 animation 加到我们的 Timeline 中。
import { Component, createElement } from './framework.js'; import { Carousel } from './carousel.js'; import { Timeline, Animation } from './animation.js'; let gallery = [ 'https://source.unsplash.com/Y8lCoTRgHPE/1600x900', 'https://source.unsplash.com/v7daTKlZzaw/1600x900', 'https://source.unsplash.com/DlkF4-dbCOU/1600x900', 'https://source.unsplash.com/8SQ6xjkxkCo/1600x900', ]; let a = <Carousel src=https://www.jb51.net/{gallery} />; // document.body.appendChild(a); a.mountTo(document.body); let tl = new Timeline(); // tl.add(new Animation({}, 'property', 0, 100, 1000, null)); tl.start();
我们发明 Animation 确实可以运作了,时间也可以得到了。可是也发明白一个问题,Animation 一直在播放没有遏制。