动画组件(wagang版)之基础篇:跳帧与延时

在前一篇随笔里提到动画抽象的可以理解成:“在dur时间内,每隔frameTime时间,播放一次animFun(per)”。
例如,要求总时间是3000ms,每隔100ms播放一次animFun(per)。我们会理论算出它应该播放0,1,2,3,...,30一共31帧的动画。
但是,事实上,由于浏览器的时间精度,或是其它的cup占用延时,或alert阻塞,或是动画本身的耗时,等等,我们没办法做到既能保证总长,又能保证间隔,又能保证帧数。这时我们就要有所取舍。
本动画提供两种选择:要么“保时丢帧”,要么“保帧延时”。

保时丢帧”,默认选择这种策略,它的好处是:能够保证到时间后,动画即刻播完。例如,在第1秒时,弹出了alert阻塞了一秒,那就会丢掉应该在这一秒内播放的10帧,alert关闭时已经到了第二秒,则跳到第二秒对应的帧继续揪放。
保帧延时”,它的好处是:保证每一帧都能播到。例如,在第1秒时,弹出了alert阻塞了一秒,alert关闭时已经到了第二秒,则还是接着阻塞前的帧继续播放,而不是跳帧。

在这一个页面,我们可以通过选择“保时丢帧”或“保帧延时”来看下它们不同的结果。
http://dev.qwrap.com/resource/js/wagang/anim/_examples/anim_bystep.html

在时间精度大略为16毫秒的情况下,每帧28秒,可以看到延时已经很明显了:
把帧间隔调到10秒,延时就更明显:


事实上,网上很多人写的动画,采用了保帧延时的策略,造成的常见现象是:如果机器慢的话,本来是0.3秒的动画,会播一两秒。

wagang版动画组件的基础类提供一个参数:byStep
{boolean} byStep (Optional) 是否按帧动画(即"不跳帧")。如果为true,表示每一帧都走到,帧数为dur/frameTime

如果是byStep动画,则是计算总步数,再按步计算进度。否则是按逝去时间与总时间的比值来计算进度。
具体的实现主要体现在step方法与内部changePer函数上:
View Code
/*
* changePer 调整播放进度,进度值
* @param {Anim} anim Anim实例
* @param {number} per 进度值,为[0,1]区间内的数值
* @returns {void}
*/
function changePer(anim, per) {
anim.per
= per;
anim._startDate
= new Date() * 1 - per * anim.dur;
if (anim.byStep) {
anim._totalStep
= anim.dur / anim.frameTime;
anim._currentStep
= per * anim._totalStep;
}
}

mix(Anim.prototype, {
/**
* 播放一帧
* @method step
* @param {number} per (Optional) 进度值,为[0,1]区间内的数值
* @returns {void}
*/
step:
function(per) {
var me = this;
if (per != null) {
changePer(me, per);
}
else {
if (me.byStep) {
per
= me._currentStep++ / me._totalStep;
}
else {
per
= (new Date() - me._startDate) / me.dur;
}
this.per = per;
}
if (this.per > 1) {
this.per = 1;
}
me.animFun(
this.per);
me.fire(
'step');
if (this.per >= 1) {
this.suspend();
return;
}
}
});

待续…………

附:QWrap网址:http://www.qwrap.com

posted on 2011-06-06 18:46  JKisJK  阅读(2413)  评论(1编辑  收藏  举报

导航