给canvas中遍历出来的框,根据重心点/底边中心点连线,并标记两个框之间的距离

原理

在画布上遍历数据画框,如果是两个有关系的数组,存一个 A 数组,遍历另一个的同时取之前存好的 A 数组的数据,根据 canvas api 画线。

效果图

在这里插入图片描述

返回值示例

在这里插入图片描述

具体实现
drawAlarmBox(row) {  //row是后端返回的值,是一组对象
      this.bigCanvas = true;
      this.$nextTick(() => {
        var canvas = document.getElementById("alarmBigCanvas");
        let arrFrame = [];
        let centerPoint = []; //底边中心
        let frames = [];
        if (row.frame.startsWith("[")) {
          frames = JSON.parse(row.frame); //得到需要画框的点的数组
        } else {
          frames = [row.frame];
        }
        var context = canvas.getContext("2d"); //建立一个 CanvasRenderingContext2D 二维渲染上下文。
        var ratioX = "";
        var ratioY = "";
        context.clearRect(0, 0, 900, 500);
        var newImg = new Image();  //创建图片对象
        // newImg.crossOrigin = 'anonymous';
        newImg.setAttribute("crossOrigin", "*");
        newImg.src = row.alarmPicture;
        arrFrame = row.frame.split("-");
        newImg.onload = () => {
          ratioX = div.accDiv(canvas.width, row.width);  //精确除出画布和图片的宽高比例
          ratioY = div.accDiv(canvas.height, row.height);
          context.drawImage(newImg, 0, 0, canvas.width, canvas.height);//在画布上画图
          context.beginPath();
          context.font = "24px sans-serif"; //文字大小
          context.fillStyle = "red"; //文字颜色
          context.fillText("文字描述", 10, 25);  //文字位置
          frames.forEach((ele, i) => { //遍历出每个报警框
            arrFrame = ele.split("-"); //根据指定符号拆分字符串
            if (arrFrame.length === 4) {
              let width = arrFrame[3] - arrFrame[2];
              let height = arrFrame[1] - arrFrame[0];
              let left = mul.accMul(ratioX, arrFrame[2]); //左
              let top = mul.accMul(ratioY, arrFrame[0]);
              let ratioWidth = mul.accMul(ratioY, width); //精确将画布比例和点之间的宽高相乘,得出相对宽高
              let ratioHeight = mul.accMul(ratioY, height); //高
              context.rect(left, top, ratioWidth, ratioHeight); //在画布上连出四个点的相对位置,即报警框
              context.font = "18px sans-serif"; //报警框内文字大小
              context.fillStyle = "#fff";//报警框内文字颜色
              context.strokeStyle = "red"; //报警框线的颜色
              context.fillText(i, left, top + 18);//报警框内文字位置
              centerPoint.push({  //※※将所有框的中心点存为对象数组,以便在遍历框和框之间关系时取值
                left: left + ratioWidth / 2,
                top: top + ratioHeight //这里高度也/2,得到的就是重心点
              });
            }
          });
          // console.log("中心", centerPoint);
          context.lineWidth = 2;
          context.stroke();
          context.closePath();
          let relationMapping =
            row.releationMapping && JSON.parse(row.releationMapping); //判断是否有框的关系字段,如果没有,不往下走
          for (let key in relationMapping) { //※※遍历框之间的关系,同时取出每两个有关系的中心点连线
            let arrIndex = key.split("-");
            var point1 = centerPoint[arrIndex[0]]; //第一个点
            var point2 = centerPoint[arrIndex[1]]; //第二个点
            if (point1 && point2) {
              //如果按index获取不到点,就不画了,画能画的关系,防止一个报错,全部画不出来
              context.fillText(
                relationMapping[key].toFixed(2) + "米",
                point1.left + (point2.left - point1.left) / 2 - 24,
                point1.top + (point2.top - point1.top) / 2 - 18
              ); //根据中心点确定距离文字的左上角坐标,标记距离
              context.beginPath();
              context.moveTo(point1.left, point1.top); //线起始位置
              context.lineTo(point2.left, point2.top); //线停止位置
              context.stroke();
            }
          }
          // 清空新创建的canvas
          this.canvasLength = 0;
        };
      });
    }
// 浮点数精确计算除
module.exports = {
  accDiv: function(num1, num2) {
    var t1, t2, r1, r2;
    try {
      t1 = num1.toString().split(".")[1].length;
    } catch (e) {
      t1 = 0;
    }
    try {
      t2 = num2.toString().split(".")[1].length;
    } catch (e) {
      t2 = 0;
    }
    r1 = Number(num1.toString().replace(".", ""));
    r2 = Number(num2.toString().replace(".", ""));
    return (r1 / r2) * Math.pow(10, t2 - t1);
  }
// 浮点数精确计算乘
module.exports = {
  accMul: function(num1, num2) {
    var m = 0,
      s1 = num1.toString(),
      s2 = num2.toString();
    try {
      m += s1.split(".")[1].length;
    } catch (e) {}
    try {
      m += s2.split(".")[1].length;
    } catch (e) {}
    return (
      (Number(s1.replace(".", "")) * Number(s2.replace(".", ""))) /
      Math.pow(10, m)
    );
  }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值