刚进公司安排了一个项目,需要一个图片进行标注的系统(参照华为云的标注),找了一圈最后觉得fabricjs比较符合当前的业务
👍👍👍目前编写代码还是比较流畅的,没有碰到很坑、很玄的问题
附上一张图
image
在Vue中使用
其实和普通操作dom差不多,在组件渲染完成后调用 const canvas = new fabric.Canvas('EL')
就可以得到fabric Canvas
对象了
需要处理
1、交互画矩形
大概思路:点击画布后触发mouse:down
事件得到画布的绝对定位点absolutePointer
,然后触发mouse:move
事件 不停的创建( new fabric.Rect)对象达到交互的作用,最后放开鼠标触发mouse:up
事件最终确定了这个矩形
ps: 需要设置画布不可选
2、拖动、缩放
拖动:贴几行关键代码 mouse:move
事件执行
if (!options.target || !options.target.selectable) {
const delta = new fabric.Point(options.e.movementX, options.e.movementY);
content.relativePan(delta);
}
缩放: 需要监听canvas容器的滚动事件并阻止原生事件
原理:滚动触发后判断是放大还是缩小,然后调用
zoomToPoint
方法
贴几行关键代码:
function zoomToPoint({ pageX = 0, pageY = 0, deltaY, zoom_size = 0.02 }) {
// 判断放大缩小
let zoom = (deltaY < 0 ? zoom_size : -zoom_size) + this.content.getZoom(); // getZoom 当前zoom
zoom = Math.max(0.1, zoom); // 限制最小
zoom = Math.min(2, zoom); // 限制最大
const zoomPoint = new fabric.Point(pageX, pageY);
this.content.zoomToPoint(zoomPoint, zoom);
}
3、判断选区是否在图片内 (简单判断)
// 验证矩形点
function validation({ x, y }) {
// 图片宽度
const iw = this.iw;
// 图片高度
const ih = this.ih;
if (x >= 0 && x <= iw) {
if (y >= 0 && y <= ih) {
return true;
}
}
return false;
}
4、数据同步
ps: 我现在的处理方法可能不是很好,好在逻辑简单,但项目目前要求不高。
当触发增加选区、删除选区、修改选区这几个数据后,重新渲染一遍canvas
碰到的问题
- 选区拖动修改后边框无法保持(目前只是一个不太好的解决方式)
content.on('object:scaling', (e) => {
const o = e.target;
if (!o.strokeWidthUnscaled && o.strokeWidth) {
o.strokeWidthUnscaled = o.strokeWidth;
}
if (o.strokeWidthUnscaled) {
o.strokeWidth = o.strokeWidthUnscaled / Math.max(o.scaleX, o.scaleY);
}
});
- 选区拉伸固定比例
const content = this.content = new fabric.Canvas(canvasId, {
uniScaleTransform: true // 拉伸不固定比例,大小跟随鼠标
});
网友评论