【发布时间】:2015-06-26 07:11:22
【问题描述】:
问题:我怎样才能让putImageData()实时更新画布,因为图像的各个部分都已经计算过了?
我正在开发一个 JavaScript/TypeScript 应用程序,以在 HTML5 <canvas> 元素上绘制 Mandelbrot 集。撇开数学和细节不谈,我的应用程序可以很好地绘制集合。但是,如果您熟悉场景的可视化,您就会知道绘制可能需要很长时间。
它会在几秒钟内绘制,但在那之前,画布是完全空白的,然后图像就会出现。我正在寻找一种方法来绘制每一行,因为它是使用putImageData() 计算的。这是我正在尝试的:
// part of the class definition
private Context: CanvasRenderingContext2D;
private ImageData: ImageData;
private Pixels: number[];
constructor() {
var c: HTMLCanvasElement = <HTMLCanvasElement>document.getElementById("can");
this.Context = c.getContext("2d");
this.ImageData = this.Context.createImageData(this.Size.Width, 1);
this.Pixels = this.ImageData.data;
}
public draw() {
// tried this... does not help
// var handler = function(m: Mandelbrot) {
// m.Context.putImageData(m.ImageData, 0, i)
// };
for(var i: number = 0; i < this.Size.Height; ++i) { // Loop over each row
for(var j: number = 0; j < this.Size.Width; ++j) { // Calc px. for one row
// all the math to compute the set... (works)
this.setPixelColor(j, color); // sets a color in this.Pixels (works)
}
// setTimeout(handler(this), 0); // does not help
this.Context.putImageData(this.ImageData, 0, i); // Draw the row on the canvas?
}
}
不知何故,putImageData() 函数在计算完图像中的一行后调用,它只显示整个图像生成后的图像。
如何让putImageData() 实时更新画布,因为每一行都已计算完毕?
非工作代码的最新更新:
var handler = function(m: Mandelbrot, i: number) {
for (var j: number = 0; j < m.Size.Width; ++j) {
// math
m.setPixelColor(j, color);
}
m.Context.putImageData(m.ImageData, 0, i);
};
var that: Mandelbrot = this;
for(var i: number = 0; i < this.Size.Height; ++i) {
setTimeout(function() {
handler(that, i)
}, 0);
}
工作代码,感谢 ekuusela:
var handler = function(m: Mandelbrot, i: number) {
return function() {
for (var j: number = 0; j < m.Size.Width; ++j) {
// math
m.setPixelColor(j, color);
}
m.Context.putImageData(m.ImageData, 0, i);
}
};
for(var i: number = 0; i < this.Size.Height; ++i) {
setTimeout(handler(this, i), 0);
}
【问题讨论】:
-
解决方案会很复杂,但基本的反应是JavaScript是单线程的,运行在UI线程上;因此,在任何代码运行时,都不会显示任何新内容。大多数 JavaScript 逻辑都可以非常快速地运行,所以这不是问题,但 Mandelbrot 集可能是基于 setTimeout 的解决方案或 Web Worker 的候选者(Web Worker 非常复杂)
-
调用 setTimeout 的行也会执行 handler,例如你可以将 handler(this, i) 包装在一个函数中,或者让 handler(this, i) 返回一个函数。
-
@ekusela 谢谢。我已经应用了你的函数包装想法,现在没有输出。听起来这个功能可能已经完成了。 JS,你又成功了。
-
尝试从处理程序返回一个函数?我认为我现在在处理程序执行时总是具有相同的值。 (不要在循环中创建函数)
-
var handler = function(...) { return function() {...}; };
标签: javascript html canvas typescript