HTML5/CSS3时代,我们要在web里做动画选择其实已经很多了:
你可以用CSS3的animattion+keyframes;
你也可以用css3的transition;
你还可以用通过在canvas上作图来实现动画,也可以借助jQuery动画相关的API方便地实现;
当然最原始的你还可以使用window.setTimout()或者window.setInterval()通过不断更新元素的状态位置等来实现动画,
现在又多了一种实现动画的方案,那就是window.requestAnimationFrame()方法
初识requestAnimationFrame
来看MDN上对其给出的诠释:
The window.requestAnimationFrame() method tells the browser that you wish to perform an
animation and requests thatthe browser call a specified function to update an animation
before the next repaint.
The method takes as an argument a callback to be invoked before the repaint.
window.requestAnimationFrame() 将告知浏览器你马上要开始动画效果了,后者需要在下次动画前调用
相应方法来更新画面。这个方法就是传递给window.requestAnimationFrame()的回调函数。
也可以说这个方法原理其实也就跟setTimeout/setInterval差不多,通过递归调用同一方法来不断更新
画面以达到动起来的效果,
但它优于setTimeout/setInterval的地方在于它是由浏览器专门为动画提供的API,在运行时浏览器会
自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销。
基本语法
可以直接调用,也可以通过window来调用,接收一个函数作为回调,返回一个ID值,通过把这个ID值传给window.cancelAnimationFrame()
可以取消该次动画。
requestAnimationFrame(callback)
requestAnimationFrame()接受一个参数,即在重绘屏幕前调用的一个函数。这个函数负责改变下一次重绘时的DOM样式。
requestAnimationFrame()只运行一次传入的函数。为了创建动画循环,可以像以前使用setTimeout()方法一样,
在每一次执行重绘方法的时候都重新设置一个定时器,然后在指定时间内重新的执行当前的方法 .
使用递归思想实现setTimeout的轮询动画:在每一次执行方法的时候都重新的设置一个定时器,然后在指定时间内
重新的执行当前的方法
->在每一次执行方法的时候首先把上一次创建的定时器清除掉
[案例]
var timer = null;
function move() {
window.clearTimeout(timer);
<js code>
timer = window.setTimeout(move, 10);
}
move();
requestAnimationFrame()做动画循环也是如此:
function updateProgress(){
var div = document.getElementById("status");
div.style.width = (parseInt(div.style.width,10)+5)+"%";
if(div.style.left !="100%"){
requestAnimationFrame(updateProgress);
}
}
requestAnimationFrame(updateProgress);
回调函数也可以接收一个参数,这个参数是一个时间码,表示下一次重绘的实际发生时间。
如果用setTimeout方法,形式大概是:setTimeout(callback,time);
如果是用requestAnimationFrame方法,形式大概是:
function callback(timestamp){ ......}
requestAnimationFrame(callback)
============================================
以下摘自:canvas中绘制的图像怎么让它移动
。什么是动画?动画是因为在每一帧的绘制中被绘制物体的显示属性不一样,比如尺寸,位置和颜色的变化。
这样在连续的绘制中,看起来就成了动画。
在计算机里的实现,就是控制每一帧画面内容。简单描述起来就是:
每一帧开始时,清空画面(无任何内容)
找到所有要显示的对象,分别按顺序绘制它们
这一帧绘制结束
就是这么简单粗暴!不断的快速得重新绘制所有内容。如果你不了解计算机绘图,可能你会觉得不能接受,
可能会觉得“就这么不停的绘制,计算机累不累啊”,但计算机就是真么工作的,而且还干的不错。
可能因为初学前端,对动画的概念停留在用css或者js控制HTML元素的位置这种高层的操作,
不了解实际上在底层,是浏览器在对页面内容进行了上面的绘制过程。canvas其实就是提供了这样一个原始的,
底层的绘制平台,让我们用JS控制绘制。
function Stage (ctx) {
this.ctx = ctx;
this.displayObjects = [];
}
Stage.prototype.add = function (displayObject) {
this.displayObjects.push(displayObject);
};
// 渲染循环
Stage.prototype.render = function () {
var displayObjects = this.displayObjects;
var ctx = this.ctx;
function loop () {
// 清空画布
ctx.clearRect(0, 0, 400, 400);
// 重绘每一个displayObject
displayObjects.forEach(function (displayObject) {
displayObject.update(ctx);
});
requestAnimationFrame(loop);
}
loop();
};
// 一个简单的display object
function Rectangle (x, y, w, h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
// display object主要是根据自己的属性知道如何绘制自己
Rectangle.prototype.update = function (ctx) {
ctx.beginPath();
ctx.rect(this.x,this.y,this.w,this.h);
ctx.stroke();
ctx.closePath();
};
var stage;
function init () {
var canvas = document.getElementById('cvs');
var ctx = canvas.getContext('2d');
// 创建两个display object
var rect = new Rectangle(10, 10, 20, 40);
var sqr = new Rectangle(50, 50, 30, 30);
stage = new Stage(ctx);
// 放入stage并开始渲染循环
stage.add(rect);
stage.add(sqr);
stage.render();
// 这里不断改变一个display object的显示属性
setInterval(function () {
rect.x = (rect.x + 1) % 400;
rect.y = (rect.y + 1) % 400;
}, 16)
}
init();
这里的例子很简单,很粗暴,但是展示了一些canvas库或者一些游戏库的绘制思想。里面有很多地方可以优化,