kissy-anim-动画的实现方式-2
上一篇的准备工作都已经就绪,还没看见我们的动画动起来啊!
现在就要开始动了。
1、上一步正则化的数据完成了,赋值到targetStyle中。
2、合并默认配置,包括动画持续时间、缓动类型(有一篇文章已经详细介绍)、回调函数。
默认配置:
defaultConfig:
duration: 1
easing: ”easeNone”
nativeSupport: true
3、Anim的关键方法,run、stop等方法是通过S.augment处理。
S.augment(Anim, EventTarget, {
/**
* @type {boolean} 是否在运行
*/
isRunning:false,
/**
* 动画开始到现在逝去的时间
*/
elapsedTime:0,
/**
* 动画开始的时间
*/
start:0,
/**
* 动画结束的时间
*/
finish:0,
/**
* 动画持续时间,不间断的话 = finish-start
*/
duration:0,
run: function() {
},
_complete:function() {
},
_runFrame:function() {
},
_nativeRun: function() {
},
stop: function(finish) {
},
_nativeStop: function(finish) {
},
_clearNativeProperty:function() {
}
});
4、继续进入run的方法中,首先初始化一堆参数,(接着尝试用fire启动anim start事件,如果fire成功那么run就完成)。
if (self.fire(EVENT_START) === false) {return;}
此处的fire结果是undefine,所以接着往下执行。
5、停止一次动画,相当于reset一次。
6、判断是否有transitionName,也就是浏览器原生的动画支持(-moz- -O- -webkit-三种特殊浏览器支持),如果有,那么就调用_nativeRun。
if (self.transitionName) {// some hack ,Weird but ff/chrome need a breaksetTimeout(function() {self._nativeRun();}, 10);} else {for (prop in target) {source[prop] = getAnimValue(elem, prop);}self.source = source;start = S.now();finish = start + duration;easing = config.easing;if (S.isString(easing)) {easing = Easing[easing] || Easing.easeNone;}self.start = start;self.finish = finish;self.easing = easing;AM.start(self);}
7、此次demo只是一个向右移动的简单动画,没有开启原生的动画支持,所以我们继续。
开始赋值一些变量,主要是source(动画目标样式)、start(动画开始的时间戳)、finish(通过duration计算动画结束时候的时间戳)、easing(动画缓动类型,并且赋值缓动函数)。
8、AM.start,此处定义在另一个manager中,这个manager专用于管理动画,有个开始定时的startTimer,每20ms启动一次动画,调用runFrame函数。如果runFrame执行完毕startTimer就停止。
9、至此,所有的流程完毕,补充runFrame这个干了些啥。 runFrame是集中管理了多个DOM的动画,每个动画还是会回到base中的runFrame中,
_runFrame:function() {var self = this,elem = self.domEl, finish = self.finish, start = self.start, duration = self.duration, time = S.now(), source = self.source, easing = self.easing, target = self.props, prop, elapsedTime; elapsedTime = time – start; var t = time > finish ? 1 : elapsedTime / duration, sp, tp, b; self.elapsedTime = elapsedTime;//S.log(“******************************** _runFrame”);for (prop in target) {sp = source[prop];tp = target[prop];// 没有发生变化的,直接略过if (eqAnimValue(prop, tp, sp)) {continue;}//S.log(prop);//S.log(tp.v + ” : ” + sp.v + ” : ” + sp.u + ” : ” + tp.u);// 比如 sp = { v: 0, u: ‘pt’} ( width: 0 时,默认单位是 pt )// 这时要把 sp 的单位调整为和 tp 的一致if (tp.v === 0) {tp.u = sp.u;}// 单位不一样时,以 tp.u 的为主,同时 sp 从 0 开始// 比如:ie 下 border-width 默认为 mediumif (sp.u !== tp.u) {//S.log(prop + ” : ” + sp.v + ” : ” + sp.u);//S.log(tp.f);sp.v = 0;sp.u = tp.u;}setAnimValue(elem, prop, tp.f(sp.v, tp.v, easing(t)) + tp.u);/*** 不能动画的量,直接设成最终值,下次不用动画,设置 dom 了*/if (tp.f == mirror) {sp.v = tp.v;sp.u = tp.u;}}if ((self.fire(EVENT_STEP) === false) || (b = time > finish)) {// complete 事件只在动画到达最后一帧时才触发self.stop(b);}}
还没有评论