我想使用Fabric.js在我的网络应用中实现橡皮擦。有没有办法在Fabric.js中实现橡皮擦?例如,如MS Paint?
答案 0 :(得分:17)
Fabric中没有内置橡皮擦,实现起来有点困难。
关于Fabric的一点是,所有东西都是基于对象的,而且大多数东西都是基于矢量的。
与原生画布不同,我们不能只删除全局位图上的某些像素。我们在下面有整个对象模型,canvas输出是渲染到画布上的所有对象的简单循环。
我们可以模仿橡皮擦的一种方法可能是在画布上放置某种叠加效果。并且在它上面划出“擦除”的线条,给出了被消灭的基础物体的幻觉。
但这仍然存在并发症:
目前我可能还没有想到更多问题。
答案 1 :(得分: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库中,
之后globalCompositeOperation: this.globalCompositeOperation,
添加:
lockMovementX: this.lockMovementX,
lockMovementY: this.lockMovementY,
然后,在您的代码中,canvas.freeDrawingBrush.id = 'erasure';
之后添加:
canvas.freeDrawingBrush.lockMovementX = true;
canvas.freeDrawingBrush.lockMovementY = true;
答案 2 :(得分:0)
我在这里写了一些解决方案的代码,并解释了它的工作方式: https://github.com/fabricjs/fabric.js/issues/1225#issuecomment-499620550
类似于@Zappescu的答案,我对内部代码进行了一些调整以达到效果;可能有更好的方法,例如在画布上通过“ path:created”事件触发路径时捕获路径,但是直到FabricJS团队决定在将来将其实现为功能时,它看起来都不会很漂亮。