将Canvas动画转换为使用requestAnimationFrame会创建无限循环

时间:2016-04-06 20:30:47

标签: javascript animation canvas

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

虽然我正在尝试将其转换为使用setTimeout转换为使用requestAnimationFrame

作为我想要完成的内容的简要概述,我将画布元素上的图像拆分为多个块,然后我想单独为这些块设置动画以重新创建“完整”图像。 (使用setTimeout的codepen非常有效。)

似乎可以通过动画获得部分内容,而且,某些块的位置会更新,但是,实际上并没有看到动画发生。

我相信我为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);
}

0 个答案:

没有答案