Fabric.js橡皮擦问题画布

问题描述 投票:9回答:3

我想使用Fabric.js在我的Web应用程序中实现橡皮擦。有没有办法在Fabric.js中实现橡皮擦?例如,在MS Paint中?

canvas coffeescript html5-canvas fabricjs
3个回答
17
投票

Fabric中没有内置的橡皮擦,实现起来有点困难。

Fabric的一点是,所有东西都是基于对象的,而且大多数东西都是基于矢量的。

与原生画布不同,我们不能只删除全局位图上的一些像素。我们在下面有整个对象模型,canvas输出是渲染到画布上的所有对象的简单循环。

我们可以模仿橡皮擦的一种方法可能是在画布上面进行某种覆盖。并且在它上面划出“擦除”的线条,给出了被消灭的基础物体的幻觉。

但是这仍然存在并发症:

  • 我们如何序列化这一层(到JSON或SVG)?
  • 如果您删除以前绘制的路径的一半然后想要使用已擦除的形状,该怎么办?形状本身需要修改;叠加不起作用。
  • 橡皮擦会影响形状还是背景颜色?背景图片怎么样?

目前我可能还没有想到更多的问题。


2
投票

我刚刚在Fabric中编写了我的橡皮擦,我希望能够回答@kangax提出的问题。

首先,如果你想要一个手写橡皮擦,你应该建立一个像这样的对象:

canvas.freeDrawingBrush = new fabric.PencilBrush(canvas);

然后我在这里略微攻击了实际的结构库(v.2.4.3):

createPath: function(pathData) {
      var path = new fabric.Path(pathData, {
        fill: null,
        stroke: this.color,
        strokeWidth: this.width,
        strokeLineCap: this.strokeLineCap,
        strokeMiterLimit: this.strokeMiterLimit,
        strokeLineJoin: this.strokeLineJoin,
        strokeDashArray: this.strokeDashArray,
        // ADDED BY AZ (24 Nov 2018)
        globalCompositeOperation: this.globalCompositeOperation,
        id: this.id
      });

使用globalCompositeOperation你可以管理你的canvas.freeDrawingBrush画一条彩色路径(你想要的颜色,我选择红色,但你也可以选择画布的背景颜色),如下所示:

canvas.isDrawingMode = 1;
canvas.freeDrawingBrush.color = "red";
canvas.freeDrawingBrush.width = 10;
canvas.freeDrawingBrush.globalCompositeOperation = 'destination-out';
canvas.freeDrawingBrush.id = 'erasure';
ctx.beginPath(); // the context of canvas
canvas.renderAll();

因此,当您将鼠标移动到画布上时,您将看到一条红色路径。当您向上移动鼠标时,最终会创建路径并应用gCO,从而删除红色路径下的所有内容。

好吧,如果你想保存画布,我更喜欢使用canvas.toSVG()功能(如果你能够管理它,它对视网膜屏幕很有用)。因此,要将画布保存为SVG,您只需要这行canvas.toSVG(),您就可以将结果存储在某处。如果要恢复画布,还应该管理“删除”ID,以便使用我的恢复功能:

function restoreSketch(imageSVG) {
  fabric.loadSVGFromString(imageSVG, function (objects, options) {
    $.each(objects, function (index, value) {
      if (value.id && value.id == 'erasure') {
        value.set({
         globalCompositeOperation: 'destination-out'
        }); //set gCO for value
      }
   });                          
   var obj = fabric.util.groupSVGElements(objects, options);
   canvas.add(obj).renderAll();
});

我希望对每个有Fabric.js头痛的人都有用

编辑:正如@Benni所建议的那样,与擦除有关的线可能会被取代。如果要将它们修复到画布上,可能会使用lockMovementX和lockMovementY稍微更改代码。所以,在fabric.js lib之后

globalCompositeOperation: this.globalCompositeOperation,

加:

lockMovementX: this.lockMovementX,
lockMovementY: this.lockMovementY,

然后,在你的代码中,在canvas.freeDrawingBrush.id = 'erasure';之后添加:

canvas.freeDrawingBrush.lockMovementX = true;
canvas.freeDrawingBrush.lockMovementY = true;

0
投票

我在这里编写了一些解决方案的代码,并解释了它是如何工作的:https://github.com/fabricjs/fabric.js/issues/1225#issuecomment-499620550

与@Zappescu的答案类似,我用内部代码稍微调整一下以达到效果;可能有更好的方法,例如当它们被来自画布的'path:created'事件触发时捕获路径,但是在FabricJS团队决定将其作为未来的功能实现之前,它看起来不会很漂亮。

© www.soinside.com 2019 - 2024. All rights reserved.