将画布动画转换为requestAnimationFrame将创建无限循环

Converting a Canvas Animation to use requestAnimationFrame creates infinite loop

本文关键字:requestAnimationFrame 创建 无限循环 转换 动画 布动画      更新时间:2024-01-31

我在这里有一个工作画布动画:http://codepen.io/lexbi/pen/KzZKze

尽管我正在尝试将其从使用setTimeout转换为使用requestAnimationFrame

作为对我试图实现的目标的简要概述,我将画布元素上的图像拆分为多个块,然后我想单独设置这些块的动画,以重新创建"完整"图像。(使用setTimeout的代码笔运行良好)。

它似乎完成了动画的一部分,并且,块的一些位置得到了更新,但是,你实际上并没有看到动画发生。

我相信我为activeBlocks对象创建的循环会提前结束。这意味着它在动画结束之前(不应该)到达这个条件中的else

    if((blocks[blocks.length-1].x != blocks[blocks.length-1].toX)){
      updateAndRender = true;
    }else{
      updateAndRender = false;
      window.cancelAnimationFrame(requestId);
    }

有人能告诉我这里做错了什么吗?

既然粘贴代码笔没有意义(因为它崩溃了),下面是我转换它的最佳尝试:

var canvas = document.getElementById("canvas"),
  context = canvas.getContext("2d"),
  img = new Image(),
  rowPieces = 10,
  columnPieces = 10,
  totalPieces = rowPieces*columnPieces,
  workingPiece = 0,
  blocks = [],
  activeBlocks = [],
  minWait = 10,
  lastTime = +new Date(),
  updateAndRender = true,
  requestId;
img.src = "http://lastresistance.com/wp-content/uploads/2014/09/ATT-fat-cat.jpg";
//   // set height & width
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
img.onload = function(){
  function theLoop(){
    var loopCount = 0;
    for(var colCount=0;colCount<columnPieces;colCount++){
      for(var rowCount=0;rowCount<rowPieces;rowCount++){
        blocks.push(
          new Block(
            (canvas.width/rowPieces), // w
            (img.width/rowPieces), // sWidth
            (canvas.height/columnPieces), // h
            (img.height/columnPieces), // sHeight
            ((img.width/rowPieces)*rowCount), //sx
            ((canvas.width/rowPieces)*rowCount), //x
            (canvas.width/rowPieces), // fromX
            ((canvas.width/rowPieces)*rowCount), // toX
            ((img.height/columnPieces)*colCount), // sy
            ((canvas.height/columnPieces)*colCount), // y
            (canvas.height/columnPieces), // fromY
            ((canvas.height/columnPieces)*colCount), // toY
            loopCount // Loop count, starting on 0
          )
        );
        loopCount++;
      }
    }
  }
  theLoop();
  function Block(w, sWidth, h, sHeight, sx, x, fromX, toX, sy, y, fromY, toY, loopCount){
    this.w = w;
    this.sWidth = sWidth;
    this.h = h;
    this.sHeight = sHeight;
    this.sx = sx;
    this.x = -x;
    this.fromX = fromX;
    this.toX = toX;
    this.sy = sy;
    this.y = -y;
    this.fromY = fromY;
    this.toY = toY;
    this.i = loopCount;
  }
  Block.prototype.update = function(){
    // so if the increment is NOT enlarged by "1" the position could final up being offset
    if(this.y < this.toY){
        this.y+=40;
    }
    //reset the y pos
    if(this.y > this.toY){
      this.y = this.toY;
    }
    // so if the increment is NOT enlarged by "1" the position could final up being offset
    if(this.x < this.toX){
      this.x+=40;
    }
    // reset the x pos
    if(this.x > this.toX){
      this.x = this.toX;
    }
  };
  Block.prototype.render = function(){
    context.drawImage(img, this.sx, this.sy, this.sWidth, this.sHeight, this.x, this.y, this.w, this.h);
  };
  //draw the screen
  function animate() {
      // This stops active blocks from growing larger than intended
      if(activeBlocks.length <= blocks.length){
        activeBlocks.push(blocks[workingPiece]);
        if(workingPiece <= totalPieces){
          workingPiece = workingPiece+1;
        }else{
          workingPiece = 0;
        }
      } // endif
      context.clearRect(0,0,canvas.width, canvas.height);
      for(var ei = 0; ei < activeBlocks.length; ++ei){
        if((blocks[blocks.length-1].x != blocks[blocks.length-1].toX)){
          updateAndRender = true;
        }else{
          updateAndRender = false;
          window.cancelAnimationFrame(requestId);
        }
        if(updateAndRender == true){
          // For some reason this still fires for 70 loops, not sure why, though this undefined IF at least stops errors in the console
          if("undefined" !== typeof activeBlocks[ei]){
            activeBlocks[ei].update();
            activeBlocks[ei].render();
            requestId = window.requestAnimationFrame(animate);
          }
        } // endif
      } // for
  };
  requestId = window.requestAnimationFrame(animate);
}

好吧,所以我处理这个问题的方式不对,这篇文章帮助我理解了更好的处理方法:http://creativejs.com/resources/requestanimationframe/

具体如下:

var fps = 15;
function draw() {
    setTimeout(function() {
        requestAnimationFrame(draw);
        // Drawing code goes here
    }, 1000 / fps);
}

本质上,我在错误的地方更新了requestAnimationFrame(draw),它应该在animate函数中。

相关文章:
  • 没有找到相关文章