【问题标题】:Can the performance of this canvas drawImage() test be improved?这个画布 drawImage() 测试的性能可以提高吗?
【发布时间】:2014-10-27 09:51:19
【问题描述】:

我有一个非常简单的循环,它以平铺方式在画布中多次绘制 8 像素 x 8 像素的图像。目前它每个循环绘制 7500 张图像。

See the jsfiddle.

var img = new Image();
img.src = 'http://i.imgur.com/3dzaMlv.png';

var W = 8;
var H = 8;
var R = 800/W;
var C = 600/H

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

var fps = document.getElementById('fps');
var timePrev = new Date().getTime();
var fpsInterval = 30;
var i = 0;

window.setInterval(function() {

    ctx.clearRect(0, 0, 800, 600);

    for (var r=0 ; r<R ; r++) {
        for (var c=0 ; c<C ; c++) {
            ctx.drawImage(img, r*W, c*H);
        }
    }

    // fps
    if (i % fpsInterval == 0) {
        var timeNow = new Date().getTime();
        var spf = (timeNow - timePrev) / fpsInterval / 1000;
        fps.innerHTML = (1/spf).toFixed(2);
        timePrev = timeNow;
    }
    i++;

}, 1000/60);

在我的 I7-2700K (3.5GHz) 处理器和 ATI Radeon HD7970 上,我得到以下帧率:

  • Chrome 36.0.1985.143 m:~40 FPS
  • Firefox 30.0:~55 FPS
  • IE 11.0.9600.17239:~35 FPS

假设我确实需要在每次更新时绘制这么多图块,是否有任何方法可以提高 FPS 性能?

编辑:为了澄清,我要求在每次更新时将它们绘制为单独的图块。因此,将它们全部渲染到屏幕外的画布上是行不通的。我对似乎表现良好的 drawImage() 调用数量感到失望。

【问题讨论】:

  • 你应该知道你已经跑题了所以去codereview.stackexchange.com
  • 谢谢 Wintermute。 I cross-posted there.
  • 实际上,绘制到屏幕外的画布正是我要做的。将每个图块绘制到屏幕外的图块,然后将整个画布爆炸到可见画布上。在这台机器上(i7-3537U - intel hd4000),性能从~22fps 到~25fps。不是一个巨大的变化,但本质上增加了 3 行代码的成本增加了 10% 以上。此外,除非您的图块具有透明区域,否则您不需要调用clearRect。 1号线。克隆现有的画布元素。 2号线。获取克隆的 ctx,(更改代码以将图块绘制到副本),第 4 行。将图像从副本绘制到屏幕画布。

标签: javascript html performance canvas


【解决方案1】:

这是使用更少 drawImage 的一种方法:

// make a template column
for(var y=0;y<ch;y+=ih){
    ctx.drawImage(img,0,y);
}

// flood-fill with the template column
for(var x=iw;x<cw;x+=iw){
    ctx.drawImage(canvas,0,0,iw,ch,x,0,iw,ch);
}

演示:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var img=new Image();
img.onload=start;
img.src="http://i.imgur.com/3dzaMlv.png";
function start(){

  var iw=img.width;
  var ih=img.height;

  // make a template column
  for(var y=0;y<ch;y+=ih){
    ctx.drawImage(img,0,y);
  }

  // flood-fill with the template column
  for(var x=iw;x<cw;x+=iw){
    ctx.drawImage(canvas,0,0,iw,ch,x,0,iw,ch);
  }

}
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid red;}
&lt;canvas id="canvas" width=300 height=300&gt;&lt;/canvas&gt;

【讨论】:

    【解决方案2】:

    使用requestAnimationFrame 代替setInterval,参见http://www.w3.org/TR/animation-timing/。你的代码可能会这样重写:http://jsfiddle.net/fv99o6jc/

    【讨论】:

      猜你喜欢
      • 2019-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-17
      • 2015-01-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多