Converting a Canvas Animation to use requestAnimationFrame creates infinite loop
<p>I have a working canvas animation here:
<a href="http://codepen.io/lexbi/pen/KzZKze" rel="nofollow">http://codepen.io/lexbi/pen/KzZKze</a></p>

<p>Though I'm trying to convert it from using <code>setTimeout</code> to use <code>requestAnimationFrame</code> instead.</p>

<p>As a brief overview of what I'm trying to accomplish, I have split up an image on a canvas element into multiple blocks, I then want to animate those blocks individually to recreate the "full" image. (The codepen using <code>setTimeout</code> works perfectly).</p>

<p>It seems to get part way through the animation, and, some of the block's positions get updated, BUT, you do not actually see the animation happen.</p>

<p>I believe that the loop that I have created for the <code>activeBlocks</code> object finishes early. Meaning it gets to the <code>else</code> in this conditional before the animation has ended (which it shouldn't):</p>

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

<p>Could someone suggest what I am doing wrong here?</p>

<p>Seeing as there is no point in pasting a codepen (because it crashes), here is my best attempt to convert it:</p>

<pre><code>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 &amp; width
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

img.onload = function(){

  function theLoop(){
    var loopCount = 0;
    for(var colCount=0;colCount&lt;columnPieces;colCount++){
      for(var rowCount=0;rowCount&lt;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 &lt; this.toY){
        this.y+=40;
    }
    //reset the y pos
    if(this.y &gt; 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 &lt; this.toX){
      this.x+=40;
    }
    // reset the x pos
    if(this.x &gt; 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 &lt;= blocks.length){
        activeBlocks.push(blocks[workingPiece]);
        if(workingPiece &lt;= totalPieces){
          workingPiece = workingPiece+1;
        }else{
          workingPiece = 0;
        }
      } // endif

      context.clearRect(0,0,canvas.width, canvas.height);

      for(var ei = 0; ei &lt; 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);
}
</code></pre>