Painter.vue 9.53 KB
<template>
  <div class="painter" ref="painter"></div>
</template>
<script>
import _ from "underscore";
import zrender from "zrender";
export default {
  props: {
    isEdit: Boolean,
    cdata: {
      type: Object,
      default: {},
    },
    list: Array,
    desk: Object,
  },
  watch: {
    cdata: {
      immediate: true,
      handler(nval) {
        if (JSON.stringify(nval) == "{}") {
          return false;
        }
        setTimeout(() => {
          if (!_.isEmpty(nval)) this.initZrender();
          console.log(this.cdata);
        }, 500);
      },
      deep: true,
    },
  },
  data() {
    return {
      pointList: [], //当前绘制的图形点位列表
      groupList: [], //图形数组
      zr: {}, //绘图实例对象
      baseColor: "#ff000075",
      strokeColor: "#f00",
      /*********************************/
      fillColor: "#f00",
      scaleVal: 10, //缩放
      rotateVal: 0, //旋转角度
      tempData: {},
      /*********************************/
      groupObj: {},
    };
  },
  methods: {
    initZrender() {
      this.$nextTick(() => {
        let client = document.querySelector(".painter").getBoundingClientRect();
        this.zr = zrender.init(this.$refs.painter, {
          renderer: "canvas",
          devicePixelRatio: 2,
          width: client.width,
          height: client.height,
        });
        this.bindingEvt();
        this.initialGroup();
      });
    },
    initialGroup() {
      //   let list = _.filter(this.list, (item) => {
      //     return this.isFloor || item.deviceSerialNum == this.cdata.serialnum;
      //   });
      //   _.each(list, (item) => {
      //     let gdata = zrender.util.clone(item);
      //     if (gdata.coordinates) {
      //       gdata.points = _.map(JSON.parse(gdata.coordinates), (point) => {
      //         let x = (point.x * this.zr.getWidth()) / 1920;
      //         let y = (point.y * this.zr.getHeight()) / 1080;
      //         return [x, y];
      //       });
      //       gdata.desk = item;
      //       console.log(gdata);
      //       this.createGroup(gdata, true);
      //     }
      //   });
      let list = this.list.filter(
        (item) => item.deviceSerialNum == this.cdata.serialnum
      );
      console.log(list);
      _.each(list, (item) => {
        let gdata = zrender.util.clone(item);
        if (gdata.coordinate) {
          gdata.points = _.map(JSON.parse(gdata.coordinate), (point) => {
            let x = (point.x * this.zr.getWidth()) / 1920;
            let y = (point.y * this.zr.getHeight()) / 1080;
            return [x, y];
          });
          gdata.desk = item;
          console.log(gdata);
          this.createGroup(gdata, true);
        }
      });
    },
    bindingEvt() {
      let that = this;
      let group;
      this.zr.on("click", (evt) => {
        if (!this.desk || _.isEmpty(this.desk)) {
          return this.$message({
            showClose: true,
            type: "warning",
            message: "请先点击选择通道",
          });
        }
        this.$emit("start", this.desk);
        let point = [evt.event.zrX, evt.event.zrY];
        this.pointList.push(point);
        if (this.pointList.length == 1) {
          //第一次点击,创建Group
          let points = zrender.util.clone(this.pointList);
          group = this.createGroup({
            points,
            fill: that.baseColor,
            desk: this.desk,
          });
        }
        this.drawPolyline(group, this.pointList);
      });
      this.zr.on("mousemove", (evt) => {
        if (this.pointList.length == 0) return false;
        let point = [evt.event.zrX, evt.event.zrY];
        this.drawPolyline(group, this.pointList.concat([point]));
      });
    },
    drawPolyline(group, points) {
      group.polyline.setShape({
        points: points,
      });
      group.points = zrender.util.clone(points);
    },
    createGroup(gdata, isFull = false) {
      let that = this;
      let points = gdata.points;

      let fill = gdata.fill;
      let position = gdata.position;
      /*******************************/
      let group = new zrender.Group({
        complete: false,
        position: position || [0, 0],
      });
      if (isFull) {
        group.points = points;
      }
      group.desk = gdata.desk;
      group.cdata = this.cdata;
      group.zr = this.zr;

      let polyline = this.createPolyline({
        stroke: that.strokeColor,
        fill: fill,
        points: points,
      });
      group.id = gdata.id || Date.now().toString(36);
      group.add(polyline);
      group.polyline = polyline;
      group.fill = gdata.fill;
      group.data = gdata;
      if (this.isEdit && points.length == 1) {
        let circle = that.createCircle(group, points[0]);
        group.add(circle);
      } else if (isFull) {
        this.drawText(group, false);
      }
      group.on("click", function (evt) {
        if (!that.isEdit) {
          evt.cancelBubble = true;
          return false;
        }
        if (group.complete) {
          that.$emit("gclick", group);
          evt.cancelBubble = true;
          return false;
        }

        if (that.pointList.length == 1) {
          //evt.cancelBubble = true;
        }
      });
      let action = this.$refs.action;
      /*action.onmouseleave = ()=>{
                action.style.display = 'none'
            }*/
      group.on("contextmenu", function (evt) {
        if (!that.isEdit) {
          evt.stop();
          return false;
        }
        if (that.pointList.length > 0) {
          evt.stop();
          return false;
        }
        action.style.display = "block";
        action.style.left = evt.offsetX - 5 + "px";
        action.style.top = evt.offsetY - 5 + "px";
        evt.stop();
        that.setCurrentGroup(this);
        return false;
      });
      this.zr.add(group);
      this.groupList.push(group);
      return group;
    },
    createCircle(group, point) {
      let that = this;
      let circle = new zrender.Circle({
        style: {
          fill: "transparent",
          stroke: "#f00",
          lineWidth: 2,
        },
        shape: {
          cx: point[0],
          cy: point[1],
          r: 10,
        },
      });
      circle.on("click", (evt) => {
        evt.cancelBubble = true;
        that.pointList.push(that.pointList[0]);
        group.remove(circle);
        if (that.pointList.length > 3) {
          this.drawPolyline(group, that.pointList);
          this.drawText(group, true);
        } else {
          this.zr.remove(group);
        }
        that.pointList = [];
      });
      return circle;
    },
    createPolyline(params) {
      let that = this;
      return new zrender.Polyline({
        x: 0,
        y: 0,
        origin: [0, 0],
        //cursor:'move',
        draggable: false,
        style: {
          stroke: params.stroke,
          fill: params.fill || that.baseColor,
          lineWidth: 3,
        },
        shape: {
          points: params.points,
          smooth: 0.01,
        },
      });
    },
    drawText(group, finish) {
      let that = this,
        xPoints = [],
        yPoints = [];
      _.each(group.points, (item) => {
        xPoints.push(item[0]);
        yPoints.push(item[1]);
      });
      let [x, y] = [
        _.max(xPoints) - _.min(xPoints),
        _.max(yPoints) - _.min(yPoints),
      ];
      let client = group.getBoundingRect();
      let content = `{name|${group.desk.name || ""}}`;

      let text = new zrender.Text({
        position: [client.x, client.y],
        style: {
          x: client.width / 2,
          y: client.height / 2,
          width: client.width,
          height: client.height,
          textAlign: "center",
          textVerticalAlign: "middle",
          //textShadowBlur: 3,
          textShadowColor: "#893e95",
          //textShadowOffsetX: 3,
          //textShadowOffsetY: 3,
          text: content,
          fill: "#fff",
          fontSize: 14,
          fontWeight: 600,
          rich: {
            name: {
              textLineHeight: 16,
              textFill: "#fff",
            },
          },
        },
      });
      //text.setClipPath(curGroup.polyline)
      //this.setDragaAble(text)
      group.add(text);
      group.text = text;
      group.complete = true; //图像已经绘制完毕
      group.polyline.attr({
        origin: [client.x + client.width / 2, client.y + client.height / 2],
      });
      if (that.isEdit) {
        that.setDragaAble(group);
      }
      this.$emit("finish", group);
    },
    setCurrentGroup(group) {
      this.groupObj = _.find(this.groupList, (item) => {
        return item.id == group.id;
      });
      this.fillColor = this.groupObj.polyline.style.fill;
    },
    setDragaAble(el, popup) {
      let isDown = false,
        downPoint = [],
        initPoint = [];
      el.on("mousedown", (evt) => {
        isDown = true;
        evt.cancelBubble = true;
        downPoint = [evt.event.zrX, evt.event.zrY];
        initPoint = zrender.util.clone(el.position);
        evt.cancelBubble = true;
      });
      el.on("mousemove", (evt) => {
        if (isDown) {
          evt.cancelBubble = true;
          let pos = [
            evt.event.zrX - downPoint[0],
            evt.event.zrY - downPoint[1],
          ];
          el.attr("position", [initPoint[0] + pos[0], initPoint[1] + pos[1]]);
        }
      });
      el.on("mouseup", (evt) => {
        evt.cancelBubble = true;
        isDown = false;
      });
      this.zr.on("mouseup", function () {
        isDown = false;
      });
    },
  },
};
</script>
<style scoped lang="less">
.painter {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
}
</style>