我创建了一个HTML5绘图应用程序,它具有基本功能,允许用户选择要绘制的颜色,更改绘图工具的大小(半径),撤消,重做和完全清除画布。
我最近添加了一个使用globalCompositionProperty(desitnation-out)的橡皮擦工具来擦除画布的选定区域。这部分工作正常,但当我去撤消擦除时,整个画布被清除,重做功能不起作用。当我使用常规绘图工具(使用source-over)恢复绘图时,撤消/重做工作。我已经包含了应用程序中使用的一些函数的代码。每次绘图工具脱离时,我都会存储画布的快照。这将添加到用于撤消和恢复画布的数组中。
有人可以解释一下我在这里做错了什么吗?我不确定我是否理解globalCompositeOperation属性如何影响已保存的画布DataURI。
function storeSnapshot() {
cStep++;
if (cStep < cPushArray.length) { cPushArray.length = cStep; }
cPushArray.push(canvas.toDataURL());
}
var putPoint = function(e){
if(dragging){
context.lineTo(e.clientX - 174, e.clientY - 50);
context.stroke();
context.beginPath();
if(eraser == true){
context.globalCompositeOperation="destination-out";
}else{
context.globalCompositeOperation="source-over";
}
context.arc(e.clientX - 174, e.clientY - 50 , radius, 0, 2 * Math.PI);
context.fill();
context.beginPath();
context.moveTo(e.clientX - 174, e.clientY - 50);
}
}
更新: 在玩了一段时间之后我尝试了一些修复我的问题的东西。我不确定这是否是正确的做事方式,但我想我会告诉你我所做的一切。
我有一个在鼠标按下时触发的脱离功能。这是以前的功能:
var disengage = function(){
dragging = false;
context.beginPath();
storeSnapshot();
}
我添加了一些代码,这允许用户使用橡皮擦工具并撤消/重做动作。我不确定为什么会这样,所以如果有人有洞察力,我会非常感激。
var disengage = function(){
dragging = false;
context.beginPath();
if(eraser == true)
{
context.globalCompositeOperation="source-over";
}
storeSnapshot();
}
答案 0 :(得分:1)
我遇到与你完全相同的问题,我很高兴我遇到了你的问题/解决方案,因为这对我来说是个灯泡。只要我看到你的解决方案,它就能完全理解发生了什么。
为了深入了解解决方案的工作原理,globalCompositeOperation
是画布的一个属性,它基本上决定了画布中的东西(在这种情况下是线条笔划)。默认情况下,它是source-over,它只是在任何现有笔划的顶部放置一个新的线条笔划。正如您所提到的,擦除使用目标输出,它将所有现有内容保留在不与新行描边重叠的位置(因此擦除)。对于一些信息图表和解释,我强烈推荐globalCompositeOperation
的MDN文档:https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
因此,如果您进入擦除模式(对您而言,擦除= true),擦除,然后立即尝试撤消,则globalCompositeOperation仍将设置为目标输出。这意味着当您的撤消尝试将存储的图像绘制到画布时,一切都将消失,因为它基本上仍在擦除(因为目标输出说,它会释放任何与新内容重叠的现有内容,在此处case是整个画布空间)。因此,您需要像在解决方案中一样将其设置回源代码,以便恢复的图像实际显示在画布上。希望这有帮助!