我正在尝试用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 ;
}

最佳答案

您需要重构一下代码:


将所有全局变量(例如canvas和context)移到循环函数之外
在循环内部,开始时清除整个画布,重新绘制正弦
使用requestAnimationFrame代替setInterval
fillRect()替换为rect(),并在内部for循环之外执行单个fill()


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

在本质上:



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);
}

<canvas id="canvas" width=800 height=500></canvas>





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

关于javascript - 使canvas的clearRect()更快地工作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27287732/

10-10 23:13