使canvas的clearRect()更快地工作

时间:2014-12-04 06:35:07

标签: javascript html5 canvas

我正在尝试用JavaScript设计旅行正弦波,但设计看起来很慢。主要瓶颈是画布清除的clearRect()

我该如何解决这个问题?

此外,我正在按ctx.fillRect(x, y,1,1)绘制像素,但当我清除使用clearRect(x, y,1,1)时,它会留下一些足迹。相反,我必须clearRect(x, y,5,5)才能获得适当的清算。可以解决什么问题?

/******************************/

var x = 0;
var sineval = [];
var offset = 0;
var animFlag;

function init() {

    for(var i=0; i<=1000; ++i){
        sineval[i] = Math.sin(i*Math.PI/180);   
    }
    // Call the sineWave() function repeatedly every 1 microseconds
    animFlag = setInterval(sineWave, 1);
    //sineWave();
}


function sineWave()
{   //console.log('Drawing Sine');

    var canvas = document.getElementById("canvas");

    if (canvas.getContext) {
        var ctx = canvas.getContext("2d");
    }

    for(x=0 ; x<1000 ;++x){

        // Find the sine of the angle
        //var i = x % 361;
        var y = sineval[x+offset];

        // If the sine value is positive, map it above y = 100 and change the colour to blue
        if(y >= 0)
        {
            y = 100 - (y-0) * 70;
            ctx.fillStyle = "green";
        }

        // If the sine value is negative, map it below y = 100 and change the colour to red
        if( y < 0 )
        {
            y = 100 + (0-y) * 70;
            ctx.fillStyle = "green";
        }

        // We will use the fillRect method to draw the actual wave. The length and breath of the
        if(x == 0) ctx.clearRect(0,y-1,5,5);
        else ctx.clearRect(x,y,5,5);
        ctx.fillRect(x, y,1,1 /*Math.sin(x * Math.PI/180) * 5, Math.sin(x * Math.PI/180 * 5)*/);

    }

    offset = (offset > 360) ? 0 : ++offset ;
}

1 个答案:

答案 0 :(得分:2)

您需要稍微重构一下代码:

  • 将所有全局变量(例如画布和上下文)移到循环函数之外
  • 在循环内部,在开头清除完整画布,重绘正弦
  • 使用requestAnimationFrame代替setInterval
  • fillRect()替换为rect(),并在内部for-loop之外执行一个fill()

使用1 ms的超时值可能会导致阻止浏览器,或者至少显着减慢浏览器的速度。考虑到监视器更新仅每16.7ms发生一次,这当然会浪费周期。如果要降低/提高正弦速度,可以减少/增加增量步长。

本质上:

&#13;
&#13;
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var sineval = [];
var offset = 0;

init();

function init() {

  for (var i = 0; i <= 1000; ++i) {
    sineval.push(Math.sin(i * Math.PI / 180));
  }

  // Call the sineWave() function
  sineWave();
}


function sineWave() {

  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

  ctx.beginPath();
  ctx.fillStyle = "green";

  // draw positive part of sine wave here
  for (var x = 0; x < 1000; x++) {
    var y = sineval[x + offset];
    if (y >= 0) {
      y = 100 - (y - 0) * 70;
      ctx.rect(x, y, 2, 2);
    }
  }

  ctx.fill();

  ctx.beginPath();
  ctx.fillStyle = "red";

  // draw negative part of sine wave here
  for (var x = 0; x < 1000; x++) {
    var y = sineval[x + offset];
    if (y < 0) {
      y = 100 - (y - 0) * 70;
      ctx.rect(x, y, 2, 2);
    }
  }
  ctx.fill();

  offset = (offset > 360) ? 0 : ++offset;
  
  requestAnimationFrame(sineWave);
}
&#13;
<canvas id="canvas" width=800 height=500></canvas>
&#13;
&#13;
&#13;

当然,如果您在<head>中加载脚本,则需要将其包装在window.onload块中,以便canvas元素可用。或者只是将脚本放在页面底部,如果还没有。