使用JavaScript 实现时间轴与动画效果的示例代码(5)

那么我们就要给它加入一个终止条件。我们这个条件判断应该放在执行 animation.run 之前,如果当前的时间已经超过了动画的时长。这个时候我们就需要停止执行动画了。

首先我们需要改造 start 函数中的 animation 循环调用,在执行 animation.run 之前加入一个条件判断。这里我们需要判断如果当前时间是否已经大于 animation 中的 duration 动画时长。如果成立动画就可以停止执行了,并且需要把这个 animation 移除 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]) { if (t > animation.duration) { this[ANIMATIONS].delete(animation); } animation.run(t); } requestAnimationFrame(this[TICK]); }; this[TICK](); } pause() {} resume() {} reset() {} add(animation) { this[ANIMATIONS].add(animation); } }

就这样我们就加入了停止条件了,并没有什么复杂的逻辑。最后我们在 main.js 中,改一下 Animation 的第一个参数。在传入的对象中加入一个 setter,这样我们就可以让我们的 animation 打印出时间。这样方便我们调试。

tl.add( new Animation( { set a(a) { console.log(a); }, }, 'property', 0, 100, 1000, null ) );

使用JavaScript 实现时间轴与动画效果的示例代码

我们看到动画确实是停止了,但是还是有一个问题。我们设置的 duration 动画时长是到 1000 毫秒,但是这里最后一个是 1002,明显超出了我们的动画时长。

所以我们是需要在遇到动画结束条件的时候,需要给 animation 传入它的 duration(动画时长的值)。这里我们就应该这样写:

start() { let startTime = Date.now(); this[TICK] = () => { let t = Date.now() - startTime; for (let animation of this[ANIMATIONS]) { let t0 = t; if (t > animation.duration) { this[ANIMATIONS].delete(animation); t0 = animation.duration; } animation.run(t0); } requestAnimationFrame(this[TICK]); }; this[TICK](); } pause() {} resume() {} reset() {} add(animation) { this[ANIMATIONS].add(animation); } }

使用JavaScript 实现时间轴与动画效果的示例代码

这样我们初步的 Timeline 和 Animation 的能力就建立起来了。

设计时间线的更新

接下来我们就给这个 Timeline 加入更多的功能,让我们 Animation 这个库变成真正的可用 。

在 CSS Animation 动画中,我们知道它有一个 duration(动画时长),其实同时还会有一个 delay(动画延迟时间)。

那么首先我们先来尝试添加这个功能。

添加 Delay 属性支持

在开发当中,当我们要去给原有的库添加功能。我们首先要考虑的是 “找到一个合理的地方去添加这个功能”。

其实直观的来说,我们第一感觉是会想把这个 delay 放入 Animation 类当中,毕竟这个功能属于动画的一部分。但是这里有一个更好的思路,就是把 delay 放到 Timeline 里面。

我们可以这么理解,一个动画的开始时间、终止时间、时间的控制,都是 Timeline 时间轴的相关事务,其实与 Animation 关注的是有区别的。而 Animation 我觉得更多是关注动画的效果,运行等事务。

所以 delay 放在 Timeline 显然是更加合适的。

在 Timeline 的 add() 方法中,添加 animation 到队列的时候,给它添加一个 delay。

在添加 delay 这个逻辑的同时,我们还可以处理掉一个问题。就是当我们在添加 animation 动画到队列的时候,可能 Timeline 已经在执行了。这样其实我们加入动画的时候,我们动画的开始时间是不对的。

另外还有一个问题,就是在 start 方法中,我们的 t 开始时间和 t0 其实不一定一致的。因为我们的 startTime 是可以根据 delay 被手动定义的。所以这一个值也是需要我们重新去编写一下逻辑的。

好,那么在实现我们的 delay 功能的同时,我们就可以把这两个因素都涵盖进去。

首先我们来加入一个 delay 参数:

export class Animation { constructor(object, property, startValue, endValue, duration, delay, timingFunction) { this.object = object; this.property = property; this.startValue = startValue; this.endValue = endValue; this.duration = duration; this.timingFunction = timingFunction; this.delay = delay; } run(time) { console.log(time); let range = this.endValue - this.startValue; this.object[this.property] = this.startValue + (range * time) / this.duration; } }

这里无非就是给 constructor 中,加入一个 delay 参数,并且存储到类的属性对象当中。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsdgjx.html