Canvas performance is a very noteworthy problem, and this time, we also encountered some points needing performance optimization when using Canvas: We used Canvas to achieve the effect of background: cover before, but this led to repeated drawing of resize and soaring CPU usage.

Use off-screen rendering

For this kind of scene, the explanation in MDN is “pre-rendering similar graphics or repetitive objects on off-screen canvas”. Of course, in fact, the explanation in MDN is not detailed enough, neither explaining why off-screen Canvas is used nor the meaning of off-screen Canvas:

We can understand the off-screen Canvas as a pre-rendering mechanism. By first drawing the whole pattern, we do not need to perform repeated image rendering in local areas, and can directly cut the image in the drawImage.

Processing before:

    
  1. function render() {
  2. draw(context); // The code is omitted
  3. }

Added off-screen rendering:

    
  1. // Render off-screen
  2. var m_canvas = document.createElement('canvas');
  3. m_canvas.width = 64; // Render the whole
  4. m_canvas.height = 64;
  5. Var m_context = m_canvas. GetContext (" 2 d ");
  6. draw(m_context);
  7. function render() {
  8. context.drawImage(m_canvas, 0, 0);
  9. }

For some post-listen rendering, creating an Image and then rendering will consume a lot of CPU. If off-screen rendering is used, the CPU usage in high-frequency events (my own is window.resize) is reduced by as much as twice.

Concentrated draw

Drawing operations can consume a lot of resources, so it is best to draw all the commands at once and store them in a buffer.

Before optimization:

    
  1. for (var i = 0; i < points.length - 1; i++) {
  2. var p1 = points[i];
  3. var p2 = points[i+1];
  4. context.beginPath();
  5. context.moveTo(p1.x, p1.y);
  6. context.lineTo(p2.x, p2.y);
  7. context.stroke();
  8. }

After the optimization:

    
  1. context.beginPath();
  2. for (var i = 0; i < points.length - 1; i++) {
  3. var p1 = points[i];
  4. var p2 = points[i+1];
  5. context.moveTo(p1.x, p1.y);
  6. context.lineTo(p2.x, p2.y);
  7. }
  8. context.stroke();

Avoid floating point coordinates

Browsers do extra work on floating point numbers to prevent aliasing. They can be rounded by a math-class function:

    
  1. CTX. DrawImage (myimage.png, Math. Floor (0.3), and Math. The floor (0.5));

Use multiple canvases to render complex scenes

For some complex scenes, it is possible to distinguish between invariant scenes and changing objects. Here is a demo, which requires smaller pixels to change and render:

    
  1. <div id="stage">
  2. <canvas id="ui-layer" width="480" height="320"></canvas>
  3. <canvas id="game-layer" width="480" height="320"></canvas>
  4. <canvas id="background-layer" width="480" height="320"></canvas>
  5. </div>
  6. <style>
  7. #stage {
  8. width: 480px;
  9. height: 320px;
  10. position: relative;
  11. border: 2px solid black
  12. }
  13. canvas { position: absolute; }
  14. #ui-layer { z-index: 3 }
  15. #game-layer { z-index: 2 }
  16. #background-layer { z-index: 1 }
  17. </style>

Further reading

  1. The optimization of canvas
  2. Canvas performance optimization – Masami Seto’s blog
  3. Improve HTML5 Canvas performance – HTML5Rocks