我正在尝试使用HTML画布制作绘图程序。您可以在此处查看其版本:https://naclcaleb.github.io/Draw
我的架构有点像这样:
我有一个主Canvas对象,其中包含它绘制的图层列表。
每层都有一个“笔画”列表。每个笔划都包含绘制它的动作列表。
我有一些滞后问题。首先,绘制列表中的所有笔画花费的时间太长。
我通过在每次添加笔划时“渲染”该图层来解决此问题,因此它只是一张图像。
效果很好,除了在用户按下Ctrl + Z时我仍然必须绘制每个笔划之外,这样我就可以重置渲染。
因此,每次他们尝试撤消操作时,计算都需要一段时间-可用,但并不理想。
为解决此问题,我对每个笔触都尝试了相同的方法-创建完笔划后,通过在不同的隐藏画布上绘制它来“渲染”它,然后将其变成带有DataURL的图像。
(注意:我确实尝试使用getImageData
和putImageData
来代替,但是它将用空像素替换以前的笔划)
现在我遇到了一个很大的问题:
每当我中风时,它就会立即消失。但是,一旦按Ctrl + Z,所有先前的笔划都会突然变为可见。
我已经尝试了一段时间了。
基本上是这里发生的事情:
释放鼠标,将触发此事件侦听器(在图层类中找到):
this.el.addEventListener("mouseup", function(e){
//You can ignore this line...
if (active){
//...and this if statement. It just handles the erasers, and has been tested to work
if (that.erasing){
CURRENT_TOOL.currentStroke.actions.push({
func: ctx.setGlobalCompositeOperation,
params: ["source-over"]
});
}
//Have the current stroke create its render - I have used console.log to ensure that this does get run, and that the dataURL produced shows the correct image.
CURRENT_TOOL.currentStroke.createRender();
//The endStroke method returns the currentStroke, which I grab here
var newStroke = CURRENT_TOOL.endStroke(ctx);
//"that" is just a reference to the layer instance
//Add it to the strokes list
that.strokes.push(newStroke);
//Update the render
that.updateRender();
}
});
正如您在事件侦听器中看到的那样,它调用updateRender
方法。这是该方法(也在图层类中):
//Clear the canvas
this.ctx.clearRect(0, 0, this.el.width, this.el.height);
//Put the LAYER's render onto the screen
this.ctx.putImageData(this.render, 0, 0);
//Draw the stroke - I'll give you the draw function, but I've confirmed it does get run
this.strokes[this.strokes.length-1].draw();
//Now get the image data and update the render
this.render = this.ctx.getImageData(0,0, this.el.width, this.el.height);
正如您在该函数中看到的那样,它调用笔触的draw函数(在stroke类中找到):
draw(){
//Ignore this if
if (this.render === undefined){
for (var i = 0;i<this.actions.length;i++){
this.actions[i].func.apply(this.ctx, this.actions[i].params);
}
}
else {
//I've used console.log to confirm that this runs.
//Draw the render
this.ctx.drawImage(this.render, 0, 0);
//I've also console.logged the dataurl of the layer before and after drawing the image, and neither have the render drawn on them.
}
}
这似乎是说this.ctx.drawImage
不在运行?还是它以错误的方式运行?
无论如何,就是这样,尽管我为这个问题的冗长性表示歉意,但我希望有人能帮助我。这真的是我的不得已。
还有一件事:通过使用与我笔触相同的方法渲染图层,我可以在前面给出的链接中工作-使用带有dataURL的图像而不是getImageData
和{{ 1}}。我不太确定该怎么想...