Javascript动画的实现原理浅析
来源: 阅读:611 次 日期:2015-03-06 11:42:59
温馨提示: 小编为您整理了“Javascript动画的实现原理浅析”,方便广大网友查阅!

这篇文章主要介绍了Javascript动画的实现原理浅析,本文用两个实例来解释Javascript动画的实现原理,需要的朋友可以参考下

假设有这样一个动画功能需求:把一个div的宽度从100px变化到200px。写出来的代码可能是这样的:

代码如下:

<div id="test1" style="width: 100px; height: 100px; background: blue; color: white;"></div>

function animate1(element, endValue, duration) {

var startTime = new Date(),

startValue = parseInt(element.style.width),

step = 1;

var timerId = setInterval(function() {

var nextValue = parseInt(element.style.width) + step;

element.style.width = nextValue + 'px';

if (nextValue >= endValue) {

clearInterval(timerId);

// 显示动画耗时

element.innerHTML = new Date - startTime;

}

}, duration / (endValue - startValue) * step);

}

animate1(document.getElementById('test1'), 200, 1000);

原理是每隔一定时间增加1px,一直到200px为止。然而,动画结束后显示的耗时却不止1s(一般是1.5s左右)。究其原因,是因为setInterval并不能严格保证执行间隔。

有没有更好的做法呢?下面先来看一道小学数学题:

代码如下:

A楼和B楼相距100米,一个人匀速从A楼走到B楼,走了5分钟到达目的地,问第3分钟时他距离A楼多远?

匀速运动中计算某个时刻路程的计算公式为:路程 * 当前时间 / 时间 。所以答案应为 100 * 3 / 5 = 60 。

这道题带来的启发是,某个时刻的路程是可以通过特定公式计算出来的。同理,动画过程中某个时刻的值也可以通过公式计算出来,而不是累加得出:

代码如下:

<div id="test2" style="width: 100px; height: 100px; background: red; color: white;"></div>

function animate2(element, endValue, duration) {

var startTime = new Date(),

startValue = parseInt(element.style.width);

var timerId = setInterval(function() {

var percentage = (new Date - startTime) / duration;

var stepValue = startValue + (endValue - startValue) * percentage;

element.style.width = stepValue + 'px';

if (percentage >= 1) {

clearInterval(timerId);

element.innerHTML = new Date - startTime;

}

}, 13);

}

animate2(document.getElementById('test2'), 200, 1000);

这样改良之后,可以看到动画执行耗时最多只会有10几ms的误差。但是问题还没完全解决,在浏览器开发工具中检查test2元素可以发现,test2的最终宽度可能不止200px。仔细检查animate2函数的代码可以发现:

1.percentage的值可能大于1,可以通过Math.min限制最大值解决。

2.即使保证了percentage的值不大于1,只要endValue或startValue为小数,(endValue - startValue) * percentage的值也可能产生误差,因为Javascript小数运算的精度不够。其实我们要保证的只是最终值的准确性,所以在percentage为1的时候,直接使用endValue即可。

于是,animate2函数的代码修改为:

代码如下:

function animate2(element, endValue, duration) {

var startTime = new Date(),

startValue = parseInt(element.style.width);

var timerId = setInterval(function() {

// 保证百分率不大于1

var percentage = Math.min(1, (new Date - startTime) / duration);

var stepValue;

if (percentage >= 1) {

// 保证最终值的准确性

stepValue = endValue;

} else {

stepValue = startValue + (endValue - startValue) * percentage;

}

element.style.width = stepValue + 'px';

if (percentage >= 1) {

clearInterval(timerId);

element.innerHTML = new Date - startTime;

}

}, 13);

}

还有最后一个疑问:setInterval的间隔为何设为13ms?原因是当下显示器的刷新率一般不超过75Hz(即每秒刷新75次,也就是每隔约13ms刷新一次),把间隔跟刷新率同步效果更好。

更多信息请查看IT技术专栏

更多信息请查看脚本栏目
由于各方面情况的不断调整与变化, 提供的所有考试信息和咨询回复仅供参考,敬请考生以权威部门公布的正式信息和咨询为准!

2025国考·省考课程试听报名

  • 报班类型
  • 姓名
  • 手机号
  • 验证码
关于我们 | 联系我们 | 人才招聘 | 网站声明 | 网站帮助 | 非正式的简要咨询 | 简要咨询须知 | 加入群交流 | 手机站点 | 投诉建议
工业和信息化部备案号:滇ICP备2023014141号-1 云南省教育厅备案号:云教ICP备0901021 滇公网安备53010202001879号 人力资源服务许可证:(云)人服证字(2023)第0102001523号
云南网警备案专用图标
联系电话:0871-65317125(9:00—18:00) 获取招聘考试信息及咨询关注公众号:
咨询QQ:526150442(9:00—18:00)版权所有:
云南网警报警专用图标
Baidu
map