以前一直没有仔细研究过程序动画,最近研究了一下,所以写写学习心得吧,温故而知新
要研究动画,首先要清楚帧的概念,几乎所有的程序动画都会表现为某种形式的循环,创建一个展现一系列图像的动画,其实就是一系列的流程图,一帧也可以说就是一幅图,然后只需要每一帧绘制出来就行了,这个是动画的基础,相信很多同学和我一样,都清楚动画片播放的原理,这里就不多说帧的概念了。
当然你既然和我一样在查看或研究动画相关内容,应该不会想当然的认为,前面所说的循环帧是依赖于编程语言中的while或者for循环来实现的吧,如果你有这种想法,就犯了初学者的错误。在javascript里面,如果要实现动画,只有依赖于setInterval或者setTimeout定时器来启动循环:
function drawSomething(){
setTimeout(drawSomething,1000/60);
....
doSomething....;
}
function drawSomething(){
....
....
doSomething....;
}
setInterval(drawSomething,1000/60);
上面两个基本的javascript定时器,相信大家都不会陌生,实现动画以前基本都是靠这两个了,当然我们为了更加方便的说明动画,这里可以使用HTML5专门为开发者提供的一个 API--requestAnimationFrame:
(function drawSomething(){
window.requestAnimationFrame(drawSomething,canvas);
....
});
,这个函数接收一个回调函数作为参数,某些浏览器中还支持第二个参数,可以通过它指定HTML元素提供动画的可视区域,当然由于是HTML5的API,肯定存在兼容性问题,为了解决这个问题,可以使用下面的方法解决
if (!window.requestAnimationFrame) {
window.requestAnimationFrame = (window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame ||
function (callback) {
return window.setTimeout(callback, 17 );
});
if (!window.cancelRequestAnimationFrame) {
window.cancelRequestAnimationFrame = (window.cancelAnimationFrame ||
window.webkitCancelRequestAnimationFrame ||
window.mozCancelRequestAnimationFrame ||
window.msCancelRequestAnimationFrame ||
window.oCancelRequestAnimationFrame ||
window.clearTimeout);
}
但是呢,并不是所有设备的绘制时间间隔是1000/60 ms,所以,就有下面这份更全面的兼容方法:
(function() {
var lastTime = 0;
var vendors = ['webkit', 'moz'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || // Webkit中此取消方法的名字变了
window[vendors[x] + 'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame) {
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16.7 - (currTime - lastTime));
var id = window.setTimeout(function() {
callback(currTime + timeToCall);
}, timeToCall);
lastTime = currTime + timeToCall;
return id;
};
}
if (!window.cancelAnimationFrame) {
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}
}());
上面一大段的代码,如果你举得看的烦,大可以 直接跳过,这只是一个预备或者收藏的代码,稍微看看即可,因为我们下面可以随时会用到requestAnimationFrame方法