fabricjs 在Vue 中的实际操作

不才
2020-02-17 12:46:57

刚进公司安排了一个项目,需要一个图片进行标注的系统(参照华为云的标注),找了一圈最后觉得fabricjs比较符合当前的业务

👍👍👍目前编写代码还是比较流畅的,没有碰到很坑、很玄的问题

附上一张图

在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

碰到的问题

  1. 选区拖动修改后边框无法保持(目前只是一个不太好的解决方式)
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);
  }
});
  1. 选区拉伸固定比例
const content = this.content = new fabric.Canvas(canvasId, {
  uniScaleTransform: true // 拉伸不固定比例,大小跟随鼠标
});