draw.js 8.69 KB
/**
 * fabric绘图
 * fab --fabric实例
 * shape --绘制的图形
 * type -- 绘制类型
*/
import { fabric } from "fabric"
class draw {
  constructor(el, type) {
    this.el = el;
    this.type = type;
    this.fab = null;
    this.drawingObject = null; //当前绘制对象
    this.mouseFrom = {} //绘制启点
    this.mouseTo = {} //绘制移动点
    this.doDrawing = false; //绘图状态
    this.selectionColor = "rgba(0,0,0,0.05)";
    this.color = red;
    this.doDrawing = false;
    this.deleteIcon =
      "data:image/svg+xml,%3C%3Fxml version='1.0' encoding='utf-8'%3F%3E%3C!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'%3E%3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='595.275px' height='595.275px' viewBox='200 215 230 470' xml:space='preserve'%3E%3Ccircle style='fill:%23F44336;' cx='299.76' cy='439.067' r='218.516'/%3E%3Cg%3E%3Crect x='267.162' y='307.978' transform='matrix(0.7071 -0.7071 0.7071 0.7071 -222.6202 340.6915)' style='fill:white;' width='65.545' height='262.18'/%3E%3Crect x='266.988' y='308.153' transform='matrix(0.7071 0.7071 -0.7071 0.7071 398.3889 -83.3116)' style='fill:white;' width='65.544' height='262.179'/%3E%3C/g%3E%3C/svg%3E";
    this.img = document.createElement("img");
    //多边形区域存储
    this.pointArray = [];
  }
  /**
   * 初始化
   */
  initFavCanvas() {
    let { el } = this;
    this.fab = new new fabric.Canvas(el, {})
  }
  /**设置绘图类型 */
  setDrawType(type) {
    this.type = type;
  }
  /**
   * 初始化绘图动作
   */
  initEvent() {
    this.fab.on("mouse:down", this.mousedownEvent)
    this.fab.on("mouse:move", this.mousemoveEvent);
    this.fab.on("mouse:up", this.mouseupEvent);
  }
  /**
   * 鼠标按下动作
   */
  mousedownEvent(e) {
    let { mouseFrom, doDrawing, drawing } = this;
    //鼠标按下坐标
    var xy = e.pointer || this.transformMouse(e.e.offsetX, e.e.offsetY);
    mouseFrom.x = xy.x;
    mouseFrom.y = xy.y;
    doDrawing = true;
    if (this.type === "polygon"){
      if (this.pointArray.length > 1) {
        if (e.target && e.target.id == this.pointArray[0].id) {
          this.generatePolygon();
        }
      }
    }
    fabdrawing(e);
  }
  /**
 * 鼠标移动
 */
  mousemoveEvent(e) {

  }
  /**
  * 鼠标抬起
  */
  mouseupEvent(e) {

  }
  /**
   * fabdrawing
   * 绘制图形
   */
  fabdrawing(e) {
    let { fab, mouseFrom, mouseTo, type, drawingObject } = this;
    if (drawingObject) {
      fab.remove(drawingObject);
    }
    var canvasObject = null;
    var left = mouseFrom.x,
      top = mouseFrom.y;
    switch (type) {
      case "arrow":
        canvasObject = this.drawArrow(e);
        break;
      case "rectangle":
        canvasObject = this.drawReacangle(e);
        break;
      case "line":
        canvasObject = this.drawReacangle(e);
        break;
      case "polygon":
          canvasObject = this.drawPolygon(e);
          break;
      default:
        break;
    }

  }
  /**
   * 坐标转换
   */
  transformMouse(mouseX, mouseY) {
    return { x: mouseX / 1, y: mouseY / 1 };
  }
  /**绘制箭头 */
  drawArrow(e) {
    let { mouseFrom, mouseTo } = this;
    var x1 = mouseFrom.x,
      x2 = mouseTo.x,
      y1 = mouseFrom.y,
      y2 = mouseTo.y;
    var w = x2 - x1,
      h = y2 - y1,
      sh = Math.cos(Math.PI / 4) * 16;
    var sin = h / Math.sqrt(Math.pow(w, 2) + Math.pow(h, 2));
    var cos = w / Math.sqrt(Math.pow(w, 2) + Math.pow(h, 2));
    var w1 = (16 * sin) / 4,
      h1 = (16 * cos) / 4,
      centerx = sh * cos,
      centery = sh * sin;
    /**
     * centerx,centery 表示起始点,终点连线与箭头尖端等边三角形交点相对x,y
     * w1 ,h1用于确定四个点
     */

    var path = " M " + x1 + " " + y1;
    path += " L " + (x2 - centerx + w1) + " " + (y2 - centery - h1);
    path +=
      " L " + (x2 - centerx + w1 * 2) + " " + (y2 - centery - h1 * 2);
    path += " L " + x2 + " " + y2;
    path +=
      " L " + (x2 - centerx - w1 * 2) + " " + (y2 - centery + h1 * 2);
    path += " L " + (x2 - centerx - w1) + " " + (y2 - centery + h1);
    path += " Z";
    return new fabric.Path(path, {
      stroke: this.color,
      fill: this.color,
      strokeWidth: this.drawWidth
    });
  }
  /**
   *绘制方形
   */
  drawReacangle(e) {
    let { mouseFrom, mouseTo } = this;
    return new fabric.Rect({
      left: left,
      top: top,
      width: mouseTo.x - left, //矩形的宽度
      height: mouseTo.y - top, //矩形的高度
      fill: "rgba(0,0,0,.3)", //填充的颜色
      stroke: "orange", // 边框原色
      strokeWidth: 1 // 边框大小
    });
  }
  /**
   * 绘制线段
   */
  drawLine(e) {
    let { mouseFrom, mouseTo } = this;
    return new fabric.Line([mouseFrom.x, mouseFrom.y, mouseTo.x, mouseTo.y],
    {
      strokeWidth: 2,
      class: "line",
      originX: "center",
      originY: "center",
      selectable: false,
      hasBorders: false,
      hasControls: false,
      evented: false,
      objectCaching: false,
      stroke: color,
      type: "line"
      }
    );
  }
  /**
   * @param {*} e
   * 绘制多边形初始化 
   */
  drawPolygon(e) {
    this.pointArray = new Array(); // 顶点集合
    this.lineArray = new Array(); //线集合
    this.canvas.isDrawingMode = false;
  }
  /**
   * 生成多边形
   */
  generatePolygon() {
    var points = new Array();
    this.pointArray.map((point, index) => {
      points.push({
        x: point.left,
        y: point.top
      });
      this.fab.remove(point);
    });
    this.lineArray.map((line, index) => {
      this.fab.remove(line);
    });
    this.fab.remove(this.activeShape).remove(this.activeLine);
    var polygon = new fabric.Polygon(points, {
      stroke: this.color,
      strokeWidth: this.drawWidth,
      fill: "rgba(255, 255, 255, 0)",
      opacity: 1,
      hasBorders: true,
      hasControls: false,
      type: "polygon"
    });
    this.fab.add(polygon);
    this.activeLine = null;
    this.activeShape = null;
    this.polygonMode = false;
    this.doDrawing = false;
    this.type = null;
    var group = this.fab.getObjects();
    var confdata = this.basconfig[this.cindex];
    confdata.roi = group;
  }
  addPoint(e) {
    var random = Math.floor(Math.random() * 10000);
    var id = new Date().getTime() + random;
    var circle = new fabric.Circle({
      radius: 5,
      fill: "#ffffff",
      stroke: "#333333",
      strokeWidth: 0.5,
      left: (e.pointer.x || e.e.layerX) / this.fab.getZoom(),
      top: (e.pointer.y || e.e.layerY) / this.fab.getZoom(),
      selectable: false,
      hasBorders: false,
      hasControls: false,
      originX: "center",
      originY: "center",
      id: id,
      objectCaching: false
    });
    if (this.pointArray.length == 0) {
      circle.set({
        fill: "red"
      });
    }
    var points = [
      (e.pointer.x || e.e.layerX) / this.fab.getZoom(),
      (e.pointer.y || e.e.layerY) / this.fab.getZoom(),
      (e.pointer.x || e.e.layerX) / this.fab.getZoom(),
      (e.pointer.y || e.e.layerY) / this.fab.getZoom()
    ];

    this.line = new fabric.Line(points, {
      strokeWidth: 2,
      fill: "#999999",
      stroke: "#999999",
      class: "line",
      originX: "center",
      originY: "center",
      selectable: false,
      hasBorders: false,
      hasControls: false,
      evented: false,
      objectCaching: false
    });
    if (this.activeShape) {
      var pos = this.fab.getPointer(e.e);
      var points = this.activeShape.get("points");
      points.push({
        x: pos.x,
        y: pos.y
      });
      var polygon = new fabric.Polygon(points, {
        stroke: "#333333",
        strokeWidth: 1,
        fill: "#cccccc",
        opacity: 0.3,

        selectable: true,
        hasBorders: false,
        hasControls: false,
        evented: false,
        objectCaching: false
      });
      polygon.drawtype = drawType;
      this.fab.remove(this.activeShape);
      this.fab.add(polygon);
      this.activeShape = polygon;
      this.fab.requestRenderAll();
    } else {
      var polyPoint = [
        {
          x: (e.pointer.x || e.e.layerX),
          y: (e.pointer.y || e.e.layerY)
        }
      ];
      var polygon = new fabric.Polygon(polyPoint, {
        stroke: "#333333",
        strokeWidth: 1,
        fill: "#cccccc",
        opacity: 0.3,
        selectable: false,
        hasBorders: false,
        hasControls: false,
        evented: false,
        objectCaching: false
      });
      this.activeShape = polygon;
      this.fab.add(polygon);
    }
    console.log("polygon", this.activeShape);
    this.activeLine = this.line;
    this.pointArray.push(circle);
    this.lineArray.push(this.line);
    this.fab.add(this.line);
    this.fab.add(circle);
  }
}