我想在使用Fabric.js的web应用程序中实现橡皮擦。是否有实现在Fabric.js中实现橡皮擦的方法?例如,就像在MS Paint中一样?
我想在使用Fabric.js的web应用程序中实现橡皮擦。是否有实现在Fabric.js中实现橡皮擦的方法?例如,就像在MS Paint中一样?
Fabric中没有内置橡皮擦,实现起来有些困难。
Fabric的特点是一切都是基于对象的,大多数东西也是基于矢量图形。
与本地画布不同,我们不能只在全局位图上擦掉一些像素。我们在画布下面有整个对象模型,并且画布输出是所有这些对象渲染到画布上的简单循环。
我们可以通过在画布顶部放置某种覆盖层来模拟橡皮擦,然后在其上绘制“擦除”的线条,从而产生底层对象被抹去的幻觉。
但是还存在以下问题:
可能还有我暂时没有考虑到的更多问题。
我刚刚在 Fabric 中编写了橡皮擦,希望能够回答 @kangax 提出的问题。
首先,如果您想要一个手写橡皮擦,您应该构建一个像这样的对象:
canvas.freeDrawingBrush = new fabric.PencilBrush(canvas);
然后,我稍微修改了实际的 Fabric 库 (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();
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();
});
globalCompositeOperation: this.globalCompositeOperation,
添加:
lockMovementX: this.lockMovementX,
lockMovementY: this.lockMovementY,
然后,在您的代码中,在 canvas.freeDrawingBrush.id = 'erasure';
之后添加:
canvas.freeDrawingBrush.lockMovementX = true;
canvas.freeDrawingBrush.lockMovementY = true;
我在这里编写了一些解决方案的代码,并解释了它的工作原理:
https://github.com/fabricjs/fabric.js/issues/1225#issuecomment-499620550
类似于@Zappescu的答案,我的答案对内部代码进行了一些调整以实现效果;可能有更好的方法,比如通过从画布中触发“path:created”事件来捕获路径,但在FabricJS团队决定在未来将其实现为功能之前,它看起来都不会很漂亮。