requestAnimationFrame



HTML5/CSS3时代,我们要在web里做动画选择其实已经很多了:
你可以用CSS3的animattion+keyframes;
你也可以用css3的transition;
你还可以用通过在canvas上作图来实现动画,也可以借助jQuery动画相关的API方便地实现;
当然最原始的你还可以使用window.setTimout()或者window.setInterval()通过不断更新元素的状态位置等来实现动画,
前提是画面的更新频率要达到每秒60次才能让肉眼看到流畅的动画效果。
现在又多了一种实现动画的方案,那就是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库或者一些游戏库的绘制思想。里面有很多地方可以优化,
比如在渲染循环里,可以减少不必要的绘制:比如两个矩形的坐标和大小都没有变化时,其实不需要不停的渲染了,
这里的渲染就是在浪费计算能力,影响性能。简答的优化就是,当display object的显示元素发生更新时,
把stage标记为dirty,只有在dirty情况下,才出发一次渲染循环。


演示: https://jsfiddle.net/ygjack/f6mtqphp/









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值