Search code examples
javascriptcanvashtml5-canvasrequestanimationframecancelanimationframe

Where to invoke cancelAnimationFrame upon completion?


I could not identify a line in step() function to indicate that the animation has completed. Therefore, I could not cancelAnimationFrame correctly.

Question: Is this the reason why cancelAnimationFrame() is not working? If yes, at which line of code do I indicate that animation has completed so I can cancelAnimationFrame?

var myRequestId;

function step() {

  // ... see https://codepen.io/jek/pen/RwwXBpz

  myRequestId = requestAnimationFrame(step);
  console.log("myRequestId", myRequestId);
}

myRequestId = requestAnimationFrame(step);

// Ref https://developer.mozilla.org/en-US/docs/Web/API/Window/cancelAnimationFrame
// todo: How do we stop it onComplete?
// question: where do we put a flag to indicate that it has completed?
//cancelAnimationFrame(myRequestId); // todo: If we uncomment this line the animation won't work at all

See https://codepen.io/jek/pen/RwwXBpz


Solution

  • You don't need to run cancelAnimationFrame, you can just run requestAnimationFrame conditionally.

    Like this:

    function step() {
      ctx.setTransform(1, 0, 0, 1, 0, 0);
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.globalAlpha = 1;
      ctx.fillStyle = "#622";
      ctx.fillRect(0, (canvas.height - scale) / 2, canvas.width, scale);
      let running = false;
      for (var i = 0; i < text.length; i++) {
        ctx.fillStyle = "#ccc";
        ctx.textBaseline = "middle";
        ctx.textAlign = "center";
        ctx.setTransform(
          1,
          0,
          0,
          1,
          Math.floor((canvas.width - scale * (text.length - 1)) / 2),
          Math.floor(canvas.height / 2)
        );
        var o = offset[i];
        while (o < 0) o++;
        o %= 1;
        var h = Math.ceil(canvas.height / 2 / scale);
        for (var j = -h; j < h; j++) {
          var c = charMap[text[i]] + j - Math.floor(offset[i]);
          while (c < 0) c += chars.length;
          c %= chars.length;
          var s = 1 - Math.abs(j + o) / (canvas.height / 2 / scale + 1);
          ctx.globalAlpha = s;
          ctx.font = scale * s + "px Helvetica";
          ctx.fillText(chars[c], scale * i, (j + o) * scale);
        }
        offset[i] += offsetV[i];
        offsetV[i] -= breaks;
        if (offsetV[i] < endSpeed) {
          offset[i] = 0;
          offsetV[i] = 0;
        } else {
          running = true;
        }
      }
      if (running) {
        requestAnimationFrame(step);
      } else {
        console.log('animation stopped');
      }
    }
    

    Live demo