【问题标题】:Optimise HTML5 canvas优化 HTML5 画布
【发布时间】:2017-08-15 02:54:31
【问题描述】:

为什么html5 canvas 在我绘制 2000 个图像时变得非常慢?
如何优化它? 这是我制作的一个演示,通过左键单击画布禁用“安全模式”并开始移动鼠标,直到绘制出大约 2000 张图像

var img = new Image()
img.src = "http://i.imgur.com/oVOibrL.png";

img.onload = Draw;

var canvas = $("canvas")[0];
var ctx    = canvas.getContext("2d")
var cnv    = $("canvas");
var draw = [];

$("canvas").mousemove(add)   

function add(event) {
    draw.push({x: event.clientX, y: event.clientY})
}

 canvas.width = cnv.width();
 canvas.height = cnv.height();

var safe = true;

cnv.contextmenu(function(e) { e.preventDefault() })

cnv.mousedown(function(event) {
    if(event.which == 1) safe = !safe;
    if(event.which == 3) draw = []
});

function Draw() {
   
    
    ctx.clearRect(0, 0, canvas.width, canvas.height);
  
  requestAnimationFrame(Draw);
  
    for(var i of draw) {
        ctx.drawImage(img, i.x, i.y)
    }   
  
  if(safe && draw.length > 300) draw = []
  
  ctx.fillText("Images count: "+ draw.length,10, 50); 
  ctx.fillText("Left click to toggle the 300 images limit",10, 70); 
  ctx.fillText("Right click to clear canvas",10, 90); 
  
}

Draw(); 
body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  position: absolute;
}

canvas {
  position: absolute;
  width: 100%;
  height: 100%;
  z-index: 99999999999;
  cursor: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas></canvas>

Codepen:http://codepen.io/anon/pen/PpeNme

【问题讨论】:

    标签: javascript html canvas


    【解决方案1】:

    用实际代码的简单方法:

    不要以这种速度重绘所有图像。

    由于在您的示例中,图像是静态的,因此您实际上不需要重绘每一帧的所有内容:只需绘制最新的。
    此外,如果您有其他绘图(例如您的文本),您可能希望只为图像使用屏幕外画布,您将在屏幕画布和其他绘图上重绘。

    var img = new Image()
    img.src = "http://i.imgur.com/oVOibrL.png";
    
    img.onload = Draw;
    
    var canvas = $("canvas")[0];
    var ctx = canvas.getContext("2d")
    var cnv = $("canvas");
    var draw = [];
    
    $("canvas").mousemove(add)
    
    function add(event) {
      draw.push({
        x: event.clientX,
        y: event.clientY
      })
    }
    
    canvas.width = cnv.width();
    canvas.height = cnv.height();
    // create an offscreen clone of our canvas for the images
    var imgCan = canvas.cloneNode();
    var imgCtx = imgCan.getContext('2d');
    
    var drawn = 0; // a counter to know how much image we've to draw
    
    var safe = true;
    
    cnv.contextmenu(function(e) {
      e.preventDefault()
    })
    
    cnv.mousedown(function(event) {
      if (event.which == 1) safe = !safe;
      if (event.which == 3) draw = []
    });
    
    function Draw() {
      // clear the visible canvas
      ctx.clearRect(0, 0, canvas.width, canvas.height);
    
      requestAnimationFrame(Draw);
      if (draw.length) { // onmy if we've got some objects to draw
        for (drawn; drawn < draw.length; drawn++) { // only the latest ones
          let i = draw[drawn];
          // draw it on the offscreen canvas
          imgCtx.drawImage(img, i.x, i.y)
        }
      }
      // should not be needed anymore but...
      if (safe && draw.length > 300) {
        draw = [];
        drawn = 0; // reset our counter
        // clear the offscren canvas
        imgCtx.clearRect(0, 0, canvas.width, canvas.height);
      }
      // draw the offscreen canvas on the visible one
      ctx.drawImage(imgCan, 0, 0);
      // do the other drawings
      ctx.fillText("Images count: " + draw.length, 10, 50);
      ctx.fillText("Left click to toggle the 300 images limit", 10, 70);
      ctx.fillText("Right click to clear canvas", 10, 90);
    
    }
    
    Draw();
    body {
      margin: 0;
      padding: 0;
      width: 100%;
      height: 100%;
      position: absolute;
    }
    
    canvas {
      position: absolute;
      width: 100%;
      height: 100%;
      z-index: 99999999999;
      cursor: none;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <canvas></canvas>

    现在,如果您需要这些图像是动态的(即在每一帧移动),您可以考虑使用 imageDatas。

    您可以通过用户@Loktar 看到此original post,它解释了如何解析您绘制的图像imageData,然后在可见画布的imageData 上按像素重绘它。也可以看this follow-up Q/A,它提供了Loktar想法的颜色实现。

    在小图像上,这实际上大大提高了性能,但不支持 Alpha 通道倍增带来了巨大的不便。您将只有完全透明和完全不透明的像素。另一个缺点是它可能更难实现,但这只是你的问题;-)

    【讨论】:

    • 您好,感谢您的回答。实际上,doge 演示工作正常,但我忘了准确地说我的图像在我正在开发的真实事物中是动态的,所以我查看了你链接到的帖子,看起来很好,但似乎很难实现。没有图书馆或正在实现这一点的东西吗?谢谢
    猜你喜欢
    • 1970-01-01
    • 2011-12-02
    • 2012-09-16
    • 1970-01-01
    • 2013-01-08
    • 1970-01-01
    • 2020-09-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多