Draw an animation using requestAnimationFrame

  • incanvasThe animation in, we can understand as,canvasDrawing the same thing over and over again. In order to better adapt to the human eye, we should draw images at an interval of 16 milliseconds.
  • Of course inJavaScriptIn thesetInterval()The function can also continue drawing after an interval of 16 milliseconds, though it will always draw at the same speed regardless of what browser the user is using or what the user is doing. It works, but it’s not very efficient.
  • requestAnimationFrameThe browser invokes the specified callback before the next redraw. At some point, when the browser is ready, the browser will call your drawing function. This gives the browser full control over the graphics, so it can reduce the frame rate as needed. You can also make the animation smoother by locking it to a screen refresh rate of 60 frames per second.

Different browsers may support different, implement a general function.

window.requestAnimFrame = (function(){ 
  return  window.requestAnimationFrame       ||  
          window.webkitRequestAnimationFrame ||  
          window.mozRequestAnimationFrame    ||  
          window.oRequestAnimationFrame      ||  
          window.msRequestAnimationFrame     ||  
          function( callback ){ 
            window.setTimeout(callback, 1000 / 60); }; }) ();Copy the code

A simple example

Let the square change to a rectangle as I move it around.

<! DOCTYPEhtml>
<html lang="en">
  <body>
    <canvas width="500" height="500" id="canvas"></canvas>
    <script type="text/javascript">
      window.requestAnimFrame = (function () {
        return (
          window.requestAnimationFrame ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame ||
          window.oRequestAnimationFrame ||
          window.msRequestAnimationFrame ||
          function (callback) {
            window.setTimeout(callback, 1000 / 60)})}) ()var canvas = document.getElementById('canvas')
      var c = canvas.getContext('2d')
      var x = 0
      var y = 0
      function drawIt() {
        window.requestAnimFrame(drawIt)
        // Clear the canvas
        c.clearRect(0.0, canvas.width, canvas.height)

        c.fillStyle = 'red'
        c.fillRect(x, 100.100.100 + y)
        x += 5
        y += 1
        if (x > 200) {
          x = 200
        }
        if (y > 200) {
          y = 200}}window.requestAnimFrame(drawIt)
    </script>
  </body>
</html>
Copy the code

Particle animations

Here we create a certain number of particles, calculate the distance between the two particles, and when the particles are within a specified distance, connect the two particles. And then you put the particles in motion, and you judge whether they’re connected by the distance between them. First we plot a certain number of particles, calculate the distance between them and then wire them up.

<! DOCTYPEhtml>
<html lang="en">
  <body>
    <canvas width="500" height="500" id="canvas"></canvas>
    <script type="text/javascript">
      // Animation compatibility functions
      window.requestAnimFrame = (function () {
        return (
          window.requestAnimationFrame ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame ||
          window.oRequestAnimationFrame ||
          window.msRequestAnimationFrame ||
          function (callback) {
            window.setTimeout(callback, 1000 / 60)})}) ()const canvas = document.getElementById('canvas')
      const context = canvas.getContext('2d')

      // Create a particle
      var dots = []
      for (var i = 0; i < 100; i++) {
        dots.push({
          x: Math.random() * canvas.width, // x, y are particle coordinates
          y: Math.random() * canvas.height,
          xa: Math.random() * 3 - 1.// xa, ya is the particle xy axis acceleration
          ya: Math.random() * 3 - 1.max: 100 // The maximum distance of the line is px})}// Draw particles
      function drawDots() {
        / / empty first
        context.clearRect(0.0, canvas.width, canvas.height)
        context.fillStyle = 'rgba (0,43,54,1)'
        context.fillRect(0.0, canvas.width, canvas.height)

        // Loop loads particles
        dots.forEach((dot) = > {
          // Particle displacement
          dot.x += dot.xa
          dot.y += dot.ya

          // Reverse the acceleration when encountering a boundary
          dot.xa *= dot.x > canvas.width || dot.x < 0 ? -1 : 1
          dot.ya *= dot.y > canvas.height || dot.y < 0 ? -1 : 1

          / / draw point
          context.fillRect(dot.x - 1, dot.y - 1.2.2)
          context.fillStyle = 'rgba(255,218,27,1)'

          drawLine(dot, dots)
        })
      }

      /** * calculate the distance and line *@param Dot Current point *@param */
      function drawLine(dot, dots) {
        for (var i = 0; i < dots.length; i++) {
          var item = dots[i]

          // Filter error messages
          if (dot === item || item.x === null || item.y === null) continue
          // Create a variable
          let xc = dot.x - item.x,
            yc = dot.y - item.y,
            dis = ' ',
            ratio = ' '

          // The distance between two particles
          dis = Math.sqrt(xc * xc + yc * yc)

          // Determine the distance between particles
          if (dis < item.max) {
            // Calculate distance ratio -- for line thickness
            ratio = (item.max - dis) / item.max
            Draw a line / /
            context.beginPath()
            context.lineWidth = ratio / 2
            context.strokeStyle = 'rgba(255,218,27,1)'
            context.moveTo(dot.x, dot.y)
            context.lineTo(item.x, item.y)
            context.stroke()
          }
        }
      }

      drawDots()
      //
    </script>
  </body>
</html>
Copy the code

The next thing is to get the canvas to draw the same thing over and over again. Simply create an animation function to execute over and over again.

.function animate() {
    requestAnimFrame(animate)
    drawDots()
}
animate()
Copy the code

Of course, we can also add mouse interaction events. First get the position of the mouse on the canvas, generate the mouse particle object, add the object to the array. When calculating the line drawing, determine whether it is a mouse object, if it is to modify the displacement speed and direction of other particles.

.// Mouse particles
let warea = {
    x: null.y: null.max: 200 // Mouse position and dot line
}
// Get the mouse coordinates when the mouse is active
window.onmousemove = (e) = > {
    warea.x = e.clientX
    warea.y = e.clientY
}
// Clear when the mouse moves out of the screen
window.onmouseout = (e) = > {
    warea.x = null
    warea.y = null}...function drawLine(dot, dots) {
    // Add mouse bit particles
    var ndots = [warea].concat(dots)

    for (var i = 0; i < ndots.length; i++) {
      var item = ndots[i]
...
    // Determine the distance between particles
    if (dis < item.max) {
        // If it is a mouse, make the other particles move towards the mouse position
        if (item === warea && dis > item.max / 2) {
          dot.x -= xc * 0.03
          dot.y -= yc * 0.03}...Copy the code

Sprite animation

What is Sprite?

In a large picture, there are many small pictures, which can be shown in different positions of the picture.

<! DOCTYPE html><html lang="en">
  <body>
    <canvas width="500" height="500" id="canvas"></canvas>
    <script type="text/javascript">
      // Animation compatibility functions
      window.requestAnimFrame = (function () {
        return (
          window.requestAnimationFrame ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame ||
          window.oRequestAnimationFrame ||
          window.msRequestAnimationFrame ||
          function (callback) {
            window.setTimeout(callback, 1000 / 60)})}) ()const canvas = document.getElementById('canvas')
      const context = canvas.getContext('2d')

      var sprite_image = new Image()
      sprite_image.src = './1.png'

      var tick = 1/ / calibration
      var x = 0
      var y = 0
      function loop() {
        tick++
        // Calculate the position
        if (tick % 10= = =0) {
          x = x + 80
          if (x === 240) {
            x = 0
            if (y === 0) {
              y = 143
            } else {
              y = 0
            }
          }

          context.clearRect(0.0, canvas.width, canvas.height)
          context.drawImage(sprite_image, x, y, 80.140.0.0.80.140)}window.requestAnimFrame(loop)
      }

      loop()
    </script>
  </body>
</html>
Copy the code

Sprite animation is actually the same object drawn in different frames of the animation. Each time we update the screen, we calculate the current frame animation (the position of the Sprite image) by the scale, then draw the image and update the scale counter.