以非阻塞方式更新HTML画布

时间:2015-03-05 05:09:06

标签: javascript html5-canvas

我正在尝试构建一个可以实时或逐帧更新HTML画布的基本渲染器。

例如,一旦绘制了像素,它就会立即更新到屏幕或等待收集一帧,然后更新(如每秒25帧)

目前我的代码并没有以任何方式发生,我不知道如何让它发挥作用。

现在,只要所有操作都完成,画布就会绘制到屏幕上。

Canvas.js:

$(document).ready(function(){
    main();
});

function main(){
    var c = document.getElementById('canvas');
    var ctx  = c.getContext("2d");

    for(var x=0; x<1000000; x++){
        drawPixel(ctx, "200", "200", "200", "255", randomNumber(0, 1000), randomNumber(0, 600));
    }
}

function drawPixel(context, red, green, blue, alpha, x, y){
    context.fillStyle = "rgba(" + red + ", " + green + ", " + blue + ", " + (alpha/255) + ")";
    context.fillRect(x, y, 1, 1);
}

function randomNumber(min, max){
    return Math.floor(Math.random()*(max-min+1)+min);
}

的index.html:

<!DOCTYPE html>
<html>
    <head>
        <title>Canvas Test</title>
        <link rel="stylesheet" type="text/css" href="styles.css" media="screen"></style>
        <meta name="viewport" content="initial-scale=1">
    </head>

    <body>
        <div class="container">
            <canvas height="600" width="1000" id="canvas">

            </canvas>
        </div>
        <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
        <script type="text/javascript" src="canvas.js"></script>
    </body>
</html>

我需要知道如何在需要时更新屏幕,而不是在代码完成后立即更新所有内容。

编辑: 基本上,我想要的是逐渐出现的所有点,以便用户可以看到积累的点。有没有办法我可以每25秒收集一次点,将其渲染为一帧并重复?

3 个答案:

答案 0 :(得分:4)

你只需打破&#34;同步性&#34;浏览器在同一个重绘中完成所有for次调用时,drawPixel循环。

相反,使用requestAnimationFrame在浏览器的自然重绘间隔(此处,而不是setTimeout或类似地)调用一次函数。类似于:

&#13;
&#13;
var canvas = document.getElementById('canvas');
var context = canvas.getContext("2d");
var counter = 0;

function run() {
  drawPixel(0, 0, 0, 255, randomNumber(0, canvas.width), randomNumber(0, canvas.height));
  counter++;
  // If our counter is less than 10000, run again at the next repaint
  if (counter < 10000) {
    window.requestAnimationFrame(run);
  }
}

function drawPixel(red, green, blue, alpha, x, y){
  context.fillStyle = "rgba(" + red + ", " + green + ", " + blue + ", " + (alpha/255) + ")";
  context.fillRect(x, y, 1, 1);
}

function randomNumber(min, max){
  return Math.floor(Math.random()*(max-min+1)+min);
}

run();
&#13;
<canvas height="100" width="100" id="canvas"></canvas>
&#13;
&#13;
&#13;

答案 1 :(得分:2)

requestAnimationFrame API可用于允许浏览器决定何时重绘。您必须解决的问题是,您的JavaScript可能需要比帧之间的16毫秒左右更长的时间。

有多种方法可以解决这个问题,但是大多数方法都涉及批量执行绘图命令。这是一个可能的解决方案:

// These variables would need to be outside the main function scope
var c = document.getElementById('canvas');
var ctx  = c.getContext("2d");
var batchSize = 1000;
var currentItem = 0;
var lastItem = 1000000;

// Execute a batch of draw commands
function main() {
  // Queue the next frame
  window.requestAnimatoinFrame(main);

  // Draw the pixels
  for(var batchEnd = currentItem + batchSize; currentItem < batchEnd; currentItem++) {
    drawPixel(ctx, ...);
  }
}

// Queue the first frame
window.requestAnimationFrame(main);

答案 2 :(得分:0)

尝试在每次迭代中使用有限数量更新的间隔计时器,如:

$(document).ready(function(){
    main();
});

function main(){
    var c = document.getElementById('canvas');
    var ctx  = c.getContext("2d");

    var pixelsPerTick = 1000;
    // one thousand iterations each tick
    window.setInterval(function(){
      for(var x=0; x<pixelsPerTick; x++){
        drawPixel(ctx, "200", "200", "200", "255", randomNumber(0, 1000), randomNumber(0, 600));
      }
    }, 1000 / 25); // 25 times per second


}

function drawPixel(context, red, green, blue, alpha, x, y){
    context.fillStyle = "rgba(" + red + ", " + green + ", " + blue + ", " + (alpha/255) + ")";
    context.fillRect(x, y, 1, 1);
}

function randomNumber(min, max){
    return Math.floor(Math.random()*(max-min+1)+min);
}