4

我无法为我绘制的对象实现“擦除”功能。我像这样绘制对象:

function draw_obj1(context) {
    context.lineTo(...)
    context.arc(...)
    //etc
}

这些是在我为画布拥有的图像背景之上绘制的(通过 context.createPattern、fillStyle = pattern 等)。

所以说上面的函数使用各种 lineTo 调用来追踪一个三角形。现在要“擦除”或“撤消”此绘图,我的一个计划是在其上重新绘制同一对象的“异或”版本,以撤消它。我通过 context.globalCompositeOperation 执行此操作(请参阅:https ://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html )。

这几乎可行,除了最终结果在我的浅蓝色背景下并不完全空白。它是一个浅灰色的三角形,而不是原来的黑线三角形。

编辑 - 忘了提及我尝试过的另一个想法。在我需要离开的区域上执行“clearRect”会在我的浅蓝色背景中产生一个白洞,这不好。

那么我应该如何撤消我绘制的线条/弧线?

干杯

4

3 回答 3

3

仅使用您的 Canvas 内容是不可能的。画布元素的反应就像一个真实的画布:因为东西被绘制,它们被合并并绑定到完整的图片。

这是因为在大多数图形 API 中,canvas 只是一个字节数组。计算机无法单独知道如何识别和区分构成当前帧的对象。

最好的方法是实现“场景图”之类的东西,即图树。然后,您可以将对象附加到此图形树并构建自己的算法以在画布上绘制每个对象。

您可以拥有一个历史数据结构,以允许撤消/重做从场景图中添加/删除对象,并在一个小时间片(纳毫秒)内重绘每个对象。

这是对您的问题的整体看法。希望您知道如何以编程方式处理图形。

更多信息:如何向 HTML5 Canvas 添加撤消功能?

在这里:http ://www.abidibo.net/blog/2011/10/12/development-undo-and-redo-functionality-canvas/

于 2012-06-04T00:52:35.380 回答
1

您应该改为执行“绘制队列”。也就是说,将在画布上完成的操作序列放入一个数组中。这种方法的好处是你所做的每一个动作都会在一个数组中被跟踪。不利的一面是必须重新绘制整个画布以适应更改。

画布动画框架大部分时间都在做这些。

一个简单的表示是这样的:

var drawingQueue = [
    {
        shape : 'rectangle',
        fill : 'red'
    },
    {
        shape : 'circle',
        fill : 'blue'
    },
    {
        shape : 'arc',
        fill : 'green'
    }
];

drawingQueue是一个命令/属性数组,用于指示在画布中绘制什么的命令。在本例中,此队列将绘制一个红色矩形、蓝色圆圈和绿色弧线。

例如,我想删除圆圈,我只需将其从数组中删除并重绘队列中的所有内容 - 现在没有圆圈。假设我们进行撤消,我们将使用数组pop()删除最后一项,然后重新绘制画布 - 现在没有弧线。

但为了更快的开发,我建议改用框架。他们将为您的形状提供内部跟踪系统,以便在画布中轻松添加和删除“元素”。首选是 KineticJS 和 FabricJS。

于 2012-06-04T00:48:53.873 回答
0
prev_comp = context.globalCompositeOperation
context.globalCompositeOperation = 'destination-out'
context.strokeStyle = "rgba(255, 255, 255, 1)"

/* Draw some "eraser" lines/shapes ..*/

context.globalCompositeOperation = prev_comp
于 2013-04-12T05:21:21.107 回答