const TICK = Symbol('tick'); const TICK_HANDLER = Symbol('tick-handler'); export class Timeline { constructor() { this[TICK] = () => { console.log('tick'); requestAnimationFrame(this[TICK]); }; } start() { this[TICK](); } pause() {} resume() {} reset() {} }
完成到这一部分,我们就可以把这个 Timeline 类引入我们的 main.js 里面试试。
import { Timeline } from './animation.js'; let tl = new Timeline(); tl.start();
Build 一下我们的代码,然后在浏览器运行,这时候就可以看到在 console 中,我们的 tick 是正常在运行了。这说明我们 Timeline 目前的逻辑是写对了。
到这里,我们实现了一个非常基本的时间线的操作。接下来我们来实现一个简单的 Animation(动画)类来测试我们的时间轴。
实现 Animation 类接下来我们给 Tick 添加一个 animation(动画),并且执行这个动画。
我们做的这个时间轴,最终是需要用在我们的 Carousel(轮播图)的动画上的。而轮播图上的动画,我们称它为 “属性动画”。
因为我们是把一个对象的某一个属性,从一个值变成量外一个值。
与属性动画相对的还有帧动画,也就是每一秒都来一张图片。讲到帧动画,我们应该都知道 “宫崎骏” 老师的动画,比如,经典的《龙猫》、《天空之城》等等。这些动画都是 “宫崎骏” 老师一张一张图画出来的,然后每一帧播放一张图片,在一个快速播放的过程,就会让我们看到图中的人和物在动了。比动漫时代更早的时候也已经有动画了,也就是我们古人所说的走马灯。
上面说到的动画,都不是通过属性来做的。但是我们在浏览器里面做的,大部分都是属性的动画。每个动画都会有一个初始属性值和终止属性值。
了解完动画的理论后,我们就可以开始实现这部分的逻辑。首先我们 Animation(动画)这部分的逻辑和 Timeline 也是相对独立的,所以这里我们可以把 Animation 单独封装成一个类。(我们后面的前端组件化的文章中还会再次强化动画库的功能。)
export class Animation { constructor() {} }
首先创建一个 Animation(动画)我们需要以下参数:
object:被赋予动画的元素对象
property:被赋予动画变动的属性
startValue:动画起始值
endValue:动画终止值
duration:动画时长
timingFunction:动画与时间的曲线
这里我们需要注意的是,传入的 property(属性)一般来说都是带有一个单位的,比如:px(像素)。因为我们的 startValue 和 endValue 一定是一个 JavaScript 里面的一个数值。那么如果我们想要一个完整的 Animation,我们还需要传入更多的参数。
但是这里我们就先不往后加,先实现一个简单的 Animation 。
初始化我们的 Animation 对象时,我们是需要把所有传入的参数都存储到这个对象的属性中,所以在 constructor 这里我们就要把所有传入的参数的原封不动的抄写一遍。
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; } }
接下来我们需要一个执行 animation(动画)的函数,我们叫它为 exec、go 都是可以的,这里我们就用 run(运行)这个单词。个人觉得更加贴切这个函数的作用。
这个函数是需要接收一个 time(时间)参数,而这个是一个虚拟时间。如果我们用真实的时间其实我们根本不需要做一个 Timeline(时间轴)了。
有了这个时间,我们就可以根据这个时间计算当前动画的属性应该变化多少。要计算这个属性的变化,我们首先需要知道动画初始值到终止值的总变化区间。
公式:变化区间(range) = 终止值(endValue) - 初始值(startValue)
得到了 变换区间 后,我们就可以计算出每一帧这个动画要变化多少,这个公式就是这样的:
变化值 = 变化区间值(range) * 时间(time) / 动画时长(duration)
这里得到的变化值,会根据当前已经执行的时间与动画的总时长算出一个 progression(进度 %),然后用这个进度的百分比与变化区间,算出我们初始值到达当前进度的值的差值。这个差值就是我们的 变化值。