记录fabricjs实际使用中的一些操作
常用技巧
以下所有案例中,均默认我已经创建了画布对象如下:
<canvas id="box"></canvas>
const fabricCanvas = new fabric.Canvas('box', {
width: 1000,
height: 600,
backgroundColor: '#fff'
});
遍历画布中所有对象
// 遍历原始画布上的所有对象
fabricCanvas.forEachObject(function(obj) {
});
等价于
fabricCanvas.getObjects().forEach(function(obj) {
});
fabricCanvas.getObjects() 是获取画布中所有元素
如果要获取当前选择的焦点元素
fabricCanvas.getActiveObject()
克隆画布中的某一个元素
fabricCanvas.forEachObject(function(obj) {
// 克隆对象
const clone = fabric.util.object.clone(obj);
// 修改克隆对象的大小为原始大小的2倍
clone.scale(scale);
});
上面的方法简单,但是在复制画布元素上有bug,会让复制的元素莫名关联原来的元素
这是官方案例http://fabricjs.com/copypaste
// 使用一个全局变量存储复制的元素,注意clone是一个异步方法!
let _clipboard = null;
function Copy() {
// clone what are you copying since you
// may want copy and paste on different moment.
// and you do not want the changes happened
// later to reflect on the copy.
canvas.getActiveObject().clone(function(cloned) {
_clipboard = cloned;
});
}
function Paste() {
// clone again, so you can do multiple copies.
_clipboard.clone(function(clonedObj) {
canvas.discardActiveObject();
clonedObj.set({
left: clonedObj.left + 10,
top: clonedObj.top + 10,
evented: true,
});
if (clonedObj.type === 'activeSelection') {
// active selection needs a reference to the canvas.
clonedObj.canvas = canvas;
clonedObj.forEachObject(function(obj) {
canvas.add(obj);
});
// this should solve the unselectability
clonedObj.setCoords();
} else {
canvas.add(clonedObj);
}
_clipboard.top += 10;
_clipboard.left += 10;
canvas.setActiveObject(clonedObj);
canvas.requestRenderAll();
});
}
其中关于的说明:https://imangodoc.com/ZLJI7A50.html
ActiveSelection类型 是 Fabric.js中的一种选择器类型,是指在canvas中选定多个对象时,选中的所有对象组成的组选对象。例如,在canvas上选中了若干个矩形或文本对象,就会创建一个ActiveSelection 对象。
将某一元素插入到指定位置
fabricCanvas.insertAt(cloneObject, index);
将画布导出为2倍图
首先声明,下面这个函数有bug,会导致生成的2倍图中的元素位置偏移!
// 导出2倍大小的图片
function exportAt2x(canvas) {
const originalWidth = canvas.width;
const originalHeight = canvas.height;
const scale = 2;
// 设置画布的新尺寸
canvas.setWidth(originalWidth * scale, { cssOnly: true });
canvas.setHeight(originalHeight * scale, { cssOnly: true });
// 将所有对象缩放到新尺寸
canvas.getObjects().forEach(function(obj) {
obj.set('scaleX', obj.get('scaleX') * scale);
obj.set('scaleY', obj.get('scaleY') * scale);
obj.setCoords();
});
// 渲染画布以应用缩放
canvas.renderAll();
// 导出为图片
const resultUrl = canvas.toDataURL({
format: 'png',
// 根据需要设置导出图片的质量
quality: 2,
width: canvas.width * scale,
height: canvas.height * scale,
left: 0,
top: 0,
});
console.log(resultUrl)
// 重置画布大小并缩放对象
canvas.setWidth(originalWidth, { cssOnly: true });
canvas.setHeight(originalHeight, { cssOnly: true });
canvas.getObjects().forEach(function(obj) {
obj.set('scaleX', obj.get('scaleX') / scale);
obj.set('scaleY', obj.get('scaleY') / scale);
obj.setCoords();
});
canvas.renderAll();
return resultUrl;
}
实际项目中,根据我使用的fabric.js-5.3.0版本发现,如果要将最终画布导出为2x图,只需要一个配置项即可:
final = fabricCanvas.toDataURL({
format: 'png',
// 根据需要设置导出图片的质量
quality: 2,
// 设置scale为2
multiplier: 2
});
在输出2倍图的同时,画布上元素位置还不会发生偏移!
调整画布中图层顺序
假设有下面3个元素
const canvas = fabricCanvas = new fabric.Canvas('canvas-box');
// 橙色矩形
rect = new fabric.Rect({
top: 30,
left: 30,
fill: 'orange',
width: 200,
height: 100
})
// 粉红色圆形
circle = new fabric.Circle({
top: 50,
left: 60,
fill: 'hotpink',
radius: 50
})
// 蓝色三角形
triangle = new fabric.Triangle({
top: 80,
left: 30,
width: 80,
height: 100,
fill: 'blue'
})
canvas.add(rect, circle, triangle)
可以看到画面中出现了矩形、圆形 和 三角形。由canvas.add(rect, circle, triangle)
方法按顺序将它们添加到画布里。可以清晰看到三个图形的层级关系。
获取当前焦点元素的层级
const currentObject = fabricCanvas.getActiveObject();
const allObjects = fabricCanvas.getObjects();
// 获取当前焦点元素的层级
const index = allObjects.indexOf(currentObject);
移至顶层
此时橙色的矩形位于最底层,如果需要将其移动到最顶层,可以使用bringToFront()
方法。
canvas.bringToFront(rect)
// 或者
// rect.bringToFront()
如果你是通过canvas
来操作的话,需要传入一个备操作的对象。本例传入的是矩形对象。
你也可以使用rect.bringToFront()
让元素操作自身。
移至底层
使用sendToBack
方法可以将元素移至最底层。
canvas.sendToBack(triangle)
// 或者
// triangle.sendToBack()
往上一层
让元素往上移动一层,可以使用bringForward
方法。
canvas.bringForward(rect)
// 或者
// rect.bringForward()
往下一层
能往上移一层,也可以往下移一层。使用的方法是sendBackwards
。
canvas.sendBackwards(triangle)
// 或者
// triangle.sendBackwards()
自定义层级
如果你需要直接设置图层层级,可以使用moveTo
方法。
如果在canvas
中使用moveTo
方法,需要传入2个参数,第一个参数是要操作的对象,第二个参数是层级。
也可以直接在元素上使用moveTo
方法,这样就只需传入1个层级参数就行。
canvas.moveTo(triangle, 10)
// 或者
triangle.moveTo(10)
可以参考 链接里的例子:https://k21vin.gitee.io/front-end-data-visualization/#/fabric/fabric-basic/fabric-moveTo