以非阻塞方式更新 HTML Canvas
Update HTML Canvas In A Non Blocking Way
我正在尝试构建一个可以实时或逐帧更新 HTML canvas 的基本渲染器。
例如,一旦绘制了一个像素,它就会立即更新到屏幕或等待收集一帧,然后再更新(比如每秒 25 帧)
目前我的代码没有以任何方式发生这种情况,我不确定如何让它工作。
现在,canvas 只有在所有操作完成后才会绘制到屏幕上。
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 秒收集一次点,将其渲染为帧并重复?
尝试使用每次迭代中更新次数有限的间隔计时器,如:
$(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);
}
您只需打破 for
循环的 "synchronousness",因为浏览器正在同一重绘中完成所有 drawPixel
调用。
相反,使用 requestAnimationFrame
在浏览器的自然重绘间隔调用一次函数(这个,而不是 setTimeout
或类似的)。类似于:
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();
<canvas height="100" width="100" id="canvas"></canvas>
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);
我正在尝试构建一个可以实时或逐帧更新 HTML canvas 的基本渲染器。
例如,一旦绘制了一个像素,它就会立即更新到屏幕或等待收集一帧,然后再更新(比如每秒 25 帧)
目前我的代码没有以任何方式发生这种情况,我不确定如何让它工作。
现在,canvas 只有在所有操作完成后才会绘制到屏幕上。
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 秒收集一次点,将其渲染为帧并重复?
尝试使用每次迭代中更新次数有限的间隔计时器,如:
$(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);
}
您只需打破 for
循环的 "synchronousness",因为浏览器正在同一重绘中完成所有 drawPixel
调用。
相反,使用 requestAnimationFrame
在浏览器的自然重绘间隔调用一次函数(这个,而不是 setTimeout
或类似的)。类似于:
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();
<canvas height="100" width="100" id="canvas"></canvas>
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);