关于Fabric的事情是一切都是基于对象的,大多数事情也是基于向量的。
与原生画布不同,我们不能仅仅删除全局位图上的一些像素。我们在下面有整个对象模型,canvas输出是所有在canvas上呈现的那些对象的一个简单的循环。
一. 我们的橡皮擦想要实现的是,擦出任意的一个部分,不能直接对对象实行删除,
实现方案一: 以白色画笔为橡皮擦,在任何上面添加一个白色来覆盖当前的颜色,
1. 如果白板有背景,
2.如果白板有黑夜模式和白天模式,白色的橡皮擦线条就会被完全的展示出来
该方案失败
二. 官方提供了 **Eraser Brush 方案来实现橡皮擦的 只需要将在文件下载到本地进行引用就好了
import '@/libs/eraser_brush.mixin.js'; // 本地地址进行引用即可
const canvas = new fabric.Canvas('c');
// 设置画笔为橡皮擦
canvas.freeDrawingBrush = new fabric.EraserBrush(canvas);
canvas.freeDrawingBrush.width = 35;
canvas.freeDrawingBrush.color = '#FFF';
canvas.isDrawingMode = true;
这样画笔就成为橡皮擦了,指哪擦那,
这时候又产生下一个问题了,1. 如果是共享白板,你的橡皮擦是应该同步到协作者哪里的。
起初天真的以为,橡皮擦也是一个画笔 path 对象,只要把画笔对象传递给协作者,就实现了整体的橡皮擦功能, 最后同步了一堆大白线过去。
查阅官方的demo
The eraser mixin uses the clipPath property of an object the apply erasing to it.
-
It creates a fabric.Group object and assigns it to the object’s clipPath.
-
It creates a fabric.Rect and adds it to the group as the first object for clipping to be successful (acts as the background for destination-out global composition operation).
-
It applies the existing clipPath property to the fabric.Rect from the previous step.
-
After erasing is done it adds fabric.Paths to create an erasing effect on the object
整体的意思大概就是 earser 不是以path 画笔的形式去实现的,是使用clipPath对象的属性对其应用擦除。
擦除完成后,它会添加fabric.Paths 以在对象上创建擦除效果,给对象创建一个 clipPath 属性,
所以这时候需要修改同步了方案了, 在橡皮擦擦除的时候,不要同画笔同步过去,不然就会同步过去一堆白色线条
path.clone(function (path) {
path.globalCompositeOperation = 'destination-out';
// http://fabricjs.com/using-transformations
var desiredTransform = fabric.util.multiplyTransformMatrices(
fabric.util.invertTransform(
obj.calcTransformMatrix()
),
path.calcTransformMatrix()
);
fabric.util.applyTransformToObject(path, desiredTransform);
clipObject.addWithUpdate(path);
obj.set({
clipPath: clipObject,
dirty: true
});
obj.fire('erasing:end', {
path: path
});
if (obj.group && Array.isArray(_this.__subTargets)) {
_this.__subTargets.push(obj);
}
});
},
看了下eraser_brush.mixin.js 的源码 发现,橡皮擦之后是有 erasing:end 事件的。可以通过erasing:end 给协作方发送消息,这里为发送方
// 这里可以监听对象
canvas.on('erasing:end', (e) => {
const {targets} = e;
// targets 为受影响的所有元素,因为橡皮擦可能一次擦了几个元素
for(let i = 0; i < targets.length; i++) {
const item = targets[i];
const str = item.TOJSON(['id']);
sendMessage(JSON.stringify(str)) // 给协作放发送橡皮擦的更改
}
})
**
接收方**
fucntion updateErasing(str) {
const canvas = new fabric.Canvas('c');
const obj = JSON.parse(str);
const item = canvas.getObjectById(obj.id);
canvas.remove(item); //先画板中的删除该元素
fabric.util.enlivenObjects([obj], (objects) => {
objects.forEach((o) => {
canvas.add(o); // 在添加经过橡皮擦之后的元素,
})
})
}
在接收方尝试过,修改 item 的 clipPath 对象,发现对 对象的修改,不能同步橡皮擦的功能
至此,fabric.js 实现橡皮擦和数据传递接收的功能就完成了
参考实例:fabricjs.com/erasing
今天的文章fabric.js 实现共享画板中的橡皮擦功能分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/21926.html