Fabric.js 的使用

需求:   摄像头抓拍图片,  在图片上绘制矩形区域, 最后将坐标上传到后台

html:

 <canvas
        id="canvas"
        width="900"
        height="600"
        style="border: 1px solid #000000"
      >
      </canvas>

 script:

(1)定义变量:

 data() {
    return {
      canvas: null,
      downPoint: null,
      upPoint: null,
      zhuangtai: true,
      src: "h111",
      position: {},
    };
  },

(2)初始化画布 + 画布监听事件:

  mounted() {
    this.canvas = new fabric.Canvas("canvas");
    this.canvas.on("mouse:down", this.canvasMouseDown);
    this.canvas.on("mouse:up", this.canvasMouseUp);
    // this.canvas.on("mouse:move", this.canvasMouseMove);
}

(3)鼠标按下:

     // 鼠标按下
    canvasMouseDown(e) {
      // 鼠标左键按下时,将当前坐标 赋值给 downPoint。{x: xxx, y: xxx} 的格式
      this.downPoint = e.absolutePointer;
    },

    // 鼠标松开
    canvasMouseUp(e) {
      // console.log(e);
      this.upPoint = e.absolutePointer;
      if (this.zhuangtai != false) {
        // 调用 创建矩形 的方法
        canvas.selection = true; // 允许框选
        //  }
        this.createRect();
      }
    }

这里记一下小坑"absolutePointer",  本来是使用的Element里面的对话框,  但是将canvas放进对话框中,是拿不到absolutePointer的.  后来将canvas放在页面中,在打印"e",   是有absolutePointer的.

(4)鼠标松开时创建矩形:

 createRect() {
      // 矩形参数计算
      let top = Math.min(this.downPoint.y, this.upPoint.y);
      let left = Math.min(this.downPoint.x, this.upPoint.x);
      let width = Math.abs(this.downPoint.x - this.upPoint.x);
      let height = Math.abs(this.downPoint.y - this.upPoint.y);

      // 矩形对象
      const rect = new fabric.Rect({
        top,
        left,
        width,
        height,
        fill: "transparent", // 填充色:透明
        stroke: "#4CEF41", // 边框/笔触颜色
        strokeWidrth: 2, // 边框/笔触宽度
        hasRotatingPoint: false, // 禁止旋转
        borderColor: "#4CEF41", //边框颜色
        // editingBorderColor: "red", //编辑框颜色
        cornerSize: 10,
        transparentCorners: false,
        cornerColor: "#4CEF41",
      });

      // 将矩形添加到画布上
      this.canvas.add(rect);
    },

(5)给画布设置背景图:

fabric.Image.fromURL(url, (img) => {
      img.set({
        // 通过scale来设置图片大小,这里设置和画布一样大
        scaleX: this.canvas.width / img.width, // 这里也可以写0 - 1
        scaleY: this.canvas.height / img.height, // 这里也可以写0 - 1
      });
      // 设置背景
      this.canvas.setBackgroundImage(
        img,
        this.canvas.renderAll.bind(this.canvas)
      );
      this.canvas.renderAll();
    });

因为我是将获得背景图的url的请求和绘制区域分成了两个页面, 本来准备通过传值的方式到绘制页面,  但我发现跳转过来后,即使拿到了url, 再将其赋值给背景图的url, 也是不能显示的.  最后通过vuex 解决了这个问题.

(6) 禁止绘制的选框 超出画布区域

        当然也是需要在松开鼠标的事件中使用

 // 鼠标松开
    canvasMouseUp(e) {
      // console.log(e);
      this.upPoint = e.absolutePointer;
      if (this.zhuangtai != false) {
        // 调用 创建矩形 的方法
        canvas.selection = true; // 允许框选
        //  }
        this.createRect();
      }
      if (this.zhuangtai == false && e.target != null) {
        // 获取画布视口边界
        let canvasBoundaries = this.canvas.calcViewportBoundaries();
        // 矩形本身
        let obj = e.target;
        // 矩形的边界
        let objBoundingRect = obj.getBoundingRect();
        // 【公式1】
        if (objBoundingRect.left < canvasBoundaries.tl.x) {
          e.target.left = canvasBoundaries.tl.x;
        }
        // console.log(objBoundingRect)
        // 【公式2】
        if (
          objBoundingRect.left + objBoundingRect.width >
          canvasBoundaries.br.x
        ) {
          e.target.left = canvasBoundaries.br.x - objBoundingRect.width;
        }

        // 【公式3】
        if (objBoundingRect.top < canvasBoundaries.tl.y) {
          e.target.top = canvasBoundaries.tl.y;
        }

        // 【公式4】
        if (
          objBoundingRect.top + objBoundingRect.height >
          canvasBoundaries.br.y
        ) {
          e.target.top = canvasBoundaries.br.y - objBoundingRect.height;
        }
        // 刷新画布
        this.canvas.renderAll();
        this.canvas.skipTargetFind = false;
      }
      this.canvas.skipTargetFind = false;
      console.log(this.canvas.getObjects()[0].aCoords.bl);
      this.position = this.canvas.getObjects()[0].aCoords;
      this.zhuangtai = false;
      console.log(this.canvas);
    },

以上是Vue版本.

以下是原生js的:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Fabric</title>
  <script src="fabric.min.js"></script>
</head>
<body>
 <canvas id="canvas" width="600" height="300" onclick="canvasMouseDown" style="border:1px solid #000000;"></canvas>
<script>
    let canvas; // 画布对象
    let zhuangtai = true;
    let topRect, leftRect, widthRect, heightRect;

    let currentType = 'default' // 当前操作模式(默认 || 创建矩形)

    let downPoint = null // 按下鼠标时的坐标
    let upPoint = null // 松开鼠标时的坐标

    // 初始化画板
    function initCanvas() {
      canvas = new fabric.Canvas('canvas')

      console.log(canvas)
      // canvas.selectionColor = 'rgba(100, 100, 255, 0.3)' // 选框填充色:半透明的蓝色
      // canvas.selectionBorderColor = 'rgba(255, 255, 255, 0.3)' // 选框边框颜色:半透明灰色
      canvas.on('mouse:down', canvasMouseDown)   // 鼠标在画布上按下
      canvas.on('mouse:up', canvasMouseUp)       // 鼠标在画布上松开
      // canvas.on('mouse:move', canvasMouseMove)       // 鼠标在画布上松开
    }
    // 鼠标在画布上按下
    function canvasMouseDown(e) {
      // 鼠标左键按下时,将当前坐标 赋值给 downPoint。{x: xxx, y: xxx} 的格式
      downPoint = e.absolutePointer
      // console.log(e)
    }
// 鼠标在画布上松开
    function canvasMouseUp(e) {
      upPoint = e.absolutePointer
      if (zhuangtai != false) {
        // 调用 创建矩形 的方法
        canvas.selection = true // 允许框选
        //  }
        createRect()
      }
      canvas.skipTargetFind = false
      // console.log( canvas.skipTargetFind)
      if (zhuangtai == false && e.target != null) {
        // 获取画布视口边界
        let canvasBoundaries = canvas.calcViewportBoundaries();
         // 矩形本身
        let obj = e.target
        // 矩形的边界
        let objBoundingRect = obj.getBoundingRect();
         // 【公式1】
        if (objBoundingRect.left < canvasBoundaries.tl.x) {
          e.target.left = canvasBoundaries.tl.x
        }
        // console.log(objBoundingRect)
         // 【公式2】
        if (objBoundingRect.left + objBoundingRect.width > canvasBoundaries.br.x) {
          e.target.left = canvasBoundaries.br.x - objBoundingRect.width
        }

        // 【公式3】
        if (objBoundingRect.top < canvasBoundaries.tl.y) {
          e.target.top = canvasBoundaries.tl.y
        }

        // 【公式4】
        if (objBoundingRect.top + objBoundingRect.height > canvasBoundaries.br.y) {
          e.target.top = canvasBoundaries.br.y - objBoundingRect.height
        }
           // 刷新画布
       canvas.renderAll()
      }
      console.log(canvas.getObjects())
      zhuangtai = false
    }
  // 创建矩形
    function createRect() {

      // 如果点击和松开鼠标,都是在同一个坐标点,不会生成矩形
      //  if (JSON.stringify(downPoint) === JSON.stringify(upPoint)) {
      //    return
      //  }
      // 创建矩形
      // 矩形参数计算(前面总结的4条公式)
      let top = topRect = Math.min(downPoint.y, upPoint.y)
      let left = leftRect = Math.min(downPoint.x, upPoint.x)
      let width = widthRect = Math.abs(downPoint.x - upPoint.x)
      let height = heightRect = Math.abs(downPoint.y - upPoint.y)

      // 矩形对象
      const rect = new fabric.Rect({
        top,
        left,
        width,
        height,
        target: "test",
        fill: 'transparent', // 填充色:透明
        stroke: '#000', // 边框颜色:黑色
        hasRotatingPoint: false  // 禁止旋转
      })

      // 将矩形添加到画布上
      canvas.add(rect)
      // console.log(canvas.getObjects())
      // 创建完矩形,清空 downPoint 和 upPoint。当然,你也可以不做这步。
      //  downPoint = null
      //  upPoint = null

    }

    // 页面加载的生命周期,在此执行 初始化画布 的操作
    window.onload = function () {
      initCanvas()
    }
  </script>
</body>
</html>

贴两个参考的链接:https://gitee.com/denghuoan/fabricjs

Fabric.js 官网: http://fabricjs.com/

猜你喜欢

转载自blog.csdn.net/weixin_39891473/article/details/128861210