可以改进这个画布drawImage()测试的性能吗?

时间:2014-09-03 02:04:18

标签: javascript html5 performance canvas

我有一个非常简单的循环,它以平铺方式在画布上多次绘制8px×8px图像。目前它每个循环绘制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()调用的数量感到失望。

2 个答案:

答案 0 :(得分:0)

使用requestAnimationFrame代替setInterval,请参阅http://www.w3.org/TR/animation-timing/。您的代码可能会被重写为:http://jsfiddle.net/fv99o6jc/

答案 1 :(得分:0)

enter image description here

这是使用更少的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);
}

演示:

&#13;
&#13;
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);
  }

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