javascript - 使 Canvas 的clearRect()工作得更快

标签 javascript html canvas

我正在尝试用 JavaScript 设计一个行波正弦波,但设计看起来相当慢。主要瓶颈是用于 Canvas 清除的 clearRect()

我该如何解决这个问题?

另外,我通过 ctx.fillRect(x, y,1,1) 绘制像素,但是当我使用 clearRect(x, y,1,1) 清除时 code>,它留下了一些足迹。相反,我必须执行 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 和上下文)移到循环函数之外
  • 在循环内,在开始时清除整个 Canvas ,重新绘制正弦
  • 使用requestAnimationFrame而不是setInterval
  • 替换fillRect()rect()并做一个fill()在内 for 循环之外

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

本质上:

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 中 block ,以便 Canvas 元素可用。或者,如果您还没有将脚本放置在页面底部,则只需将其放置在页面底部即可。

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

相关文章:

javascript 我们应该尽可能共享函数还是创建新函数?

javascript - VueJs 中的 Highmaps...将 State 传递给 mapOptions

c# - WPF 保存 Canvas ,然后从持久状态中将其取回

javascript - Blob 图像无法使用 JavaScript 进入 Canvas

javascript - 如果元素的后代包含特定单词,则执行代码的 Jquery

javascript - 根据 URL 参数过滤 'ng-repeat'

html - CSS 问题,:checked state doesn't work

javascript - 为什么更改 Canvas 大小后必须重新绘制图像?

Javascript - PHP 在 JavaScript 上的 Substr() 替代品

javascript - 未捕获的类型错误 : toUpperCase is not a function when binding option dynamically to data-tokens bootstrap