如何撤消HTML5画布绘图应用程序的橡皮擦操作



我创建了一个HTML5绘图应用程序,该应用程序具有基本功能,允许用户选择要绘制的颜色、更改绘图工具的大小(半径)、撤消、重做和完全清除画布。

我最近添加了一个橡皮擦工具,使用globalCompositionProperty(desitnation-out)来擦除画布的选定区域。这部分工作得很好,但当我去撤消擦除时,整个画布都被清除了,重做功能也不起作用。当我继续使用常规绘图工具(使用源代码)进行绘图时,撤消/重做会起作用。我已经包含了应用程序中使用的一些功能的代码。每次断开绘图工具时,我都会存储画布的快照。它被添加到用于撤消和恢复画布的数组中。

有人能解释一下我在这里可能做错了什么吗?我不确定我是否理解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();
    }

我遇到了和你完全相同的问题,我很高兴看到你的问题/解决方案,因为这对我来说是一个激动人心的时刻。我一看到你的解决方案,就完全明白发生了什么。

为了深入了解解决方案的工作原理,globalCompositeOperation是画布的一个属性,它基本上决定了如何在画布上放置东西,在本例中是线条笔划。默认情况下,它是源覆盖,只会在任何现有笔划的顶部放置一个新线笔划。正如您所提到的,擦除使用destination out,它将所有现有内容保留在不与新行笔划重叠的位置(因此擦除)。对于一些信息丰富的图表和解释,我强烈推荐globalCompositeOperation的MDN文档:https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation

因此,如果您进入擦除模式(对您来说,橡皮擦=true),擦除,然后立即尝试撤消,globalCompositeOperation仍将设置为destination out。这意味着,当您的撤消尝试将存储的图像绘制到画布上时,所有内容都将消失,因为它本质上仍在擦除(正如destination out所说,它将丢弃与新内容重叠的任何现有内容,在这种情况下,这是整个画布空间)。因此,您需要像在解决方案中那样将其设置回源位置,以便恢复的图像实际显示在画布上。希望这能有所帮助!

最新更新