基于Vue3+LeaderLine实现画线测距及线条自由调整

先看下效果:我们画线后可以根据比例关系自动计算距离,并且线条不对可以自由调整
在这里插入图片描述

<template>
  <div id="image-detail">
    <el-image :src="myImageUrl" style="height: auto; width: 800px;" fit="scale-down" ref="canvasRef" @mousedown="startDrawing" @mousemove="drawLine" @mouseup="stopDrawing">
      <template #error>
        <div>
          <el-icon></el-icon>
        </div>
      </template>
    </el-image>
  </div>
</template>

<script>
import LeaderLine from 'leader-line'
import $ from 'jquery'

export default {
    
    
  ...
  methods: {
    
    
    startDrawing(event) {
    
    
      console.log("当前坐标点:" + event.offsetX + " " + event.offsetY)
      if (this.checkIfAiPoint(event)) return
    },
    drawLine(event) {
    
    
      const self = this
      if (self.ai.isAiMoving) {
    
    
        self.aiMoving(event)
        return false
      }
    },
    stopDrawing(event) {
    
    
      if (this.checkIfAiPoint(event)) return
    },
    // AI结果画图
    markPointPlus(offsetX, offsetY, tag, nameIndex) {
    
    
      const self = this
      if (document.getElementById("image-detail") === null) {
    
    
        return
      }
      
      // 点击多个点,生成多个值
      let div = document.createElement("div");
      div.className = "marker";

      div.id = "marker" + nameIndex + 'ai' + tag;
      div.style.width = 0
      div.style.height = 0
      // 红点颜色
      div.style.backgroundColor = "red";
      div.style.zIndex = 999;
      div.style.left = offsetX + "px";
      let imageHeight = $('#image-detail').height()
      div.style.top = (offsetY - imageHeight) + "px";
      div.style.position = "relative";
      // 边框半径百分比
      div.style.borderRadius = "50%";
      // 该位置监听的偏移量有问题,需计算
      // div.onclick = function (event) {
    
    
      //   // 计算出相对图片的偏移量
      //   console.log($('#image-detail .el-image__inner').left)
      //   console.log($('#image-detail .el-image__inner').top)
      //   const offsetX = event.clientX - $('#image-detail .el-image__inner').left
      //   const offsetY = event.clientY - $('#image-detail .el-image__inner').top
      //   if (self.ai.isAiMoving) {
    
    
      //     // 停止移动
      //     self.stopAiMoving(offsetX, offsetY, nameIndex, tag)
      //   } else {
    
    
      //     // 开始移动
      //     self.startAiMoving(offsetX, offsetY, nameIndex, tag)
      //   }
      // },
      document.getElementById("image-detail").appendChild(div);
      self.aiLineStartMiddleInfo[nameIndex + tag] = {
    
    'offsetX': offsetX, 'offsetY': offsetY}
    },
    startAiMoving(offsetX, offsetY, nameIndex, tag) {
    
    
      const self = this
      // 说明鼠标刚刚从原来位置up,不需要开始
      if (offsetX === self.lastAiX && offsetY === self.lastAiY) {
    
    
        return false
      }
      self.ai.isAiMoving = true
      self.ai.nameIndex = nameIndex
      self.ai.tag = tag
      self.lastAiX = offsetX
      self.lastAiY = offsetY
    },
    aiMoving(event) {
    
    
      const self = this
      const nameIndex = self.ai.nameIndex
      let imageHeight = $('#image-detail').height()
      if (!this.ai.isAiMoving) return;
      // const len = Object.keys(self.aiDrawInfo).length
      // 由于之前在开始结束位置新增了点的宽高均为4导致
      // 解决开始端移动点上移问题,原因未知, 由多点规律推断而来
      // if (self.ai.tag === 'start') {
    
    
      //   $('#marker' + nameIndex + 'ai' + self.ai.tag).css({
    
    
      //     'left': event.offsetX,
      //     'top': (event.offsetY + 4 * (len - nameIndex) * 2 - imageHeight)
      //   })
      // } else {
    
    
      //   $('#marker' + nameIndex + 'ai' + self.ai.tag).css({
    
    
      //     'left': event.offsetX,
      //     'top': (event.offsetY + 4 * ((len - nameIndex) * 2 - 2) - imageHeight)
      //   })
      // }
      $('#marker' + nameIndex + 'ai' + self.ai.tag).css({
    
    
        'left': event.offsetX,
        'top': (event.offsetY - imageHeight)
      })
      const lineRef = self.aiDrawInfo['marker' + nameIndex + 'ai']
      lineRef.position()
    },
    stopAiMoving(currOffsetX, currOffsetY, nameIndex, tag) {
    
    
      const self = this
      nameIndex = Number(nameIndex)
      // 说明鼠标刚刚从原来位置up,不需要结束
      if (currOffsetX === self.lastAiX && currOffsetY === self.lastAiY) {
    
    
        return false
      }
      self.ai.isAiMoving = false
      self.ai.nameIndex = 0
      self.ai.tag = ''
      let offsetX
      let offsetY
      if (tag === 'start') {
    
    
        offsetX = self.aiLineStartMiddleInfo[nameIndex + 'middle']['offsetX']
        offsetY = self.aiLineStartMiddleInfo[nameIndex + 'middle']['offsetY']
      } else {
    
    
        offsetX = self.aiLineStartMiddleInfo[nameIndex + 'start']['offsetX']
        offsetY = self.aiLineStartMiddleInfo[nameIndex + 'start']['offsetY']
      }
      const currDistance = Math.sqrt((currOffsetX - offsetX) ** 2 + (currOffsetY - offsetY) ** 2)
      let currRealDistance = (self.rulerRealDistance * 100 / self.rulerDistance * currDistance / 100).toFixed(1)
      // 判断是否为标尺移动
      if (nameIndex === 0) {
    
    
        self.rulerDistance = currDistance
        // 重新计算其他所有的画线距离
        this.recalculateAiByRuler()
      } else {
    
    
        const lineRef = self.aiDrawInfo['marker' + nameIndex + 'ai']
        lineRef.setOptions({
    
    'endLabel': currRealDistance + 'mm'})
      }++-
      // 同时更新坐标信息
      self.aiLineStartMiddleInfo[nameIndex + tag]['offsetX'] = currOffsetX
      self.aiLineStartMiddleInfo[nameIndex + tag]['offsetY'] = currOffsetY
      self.lastAiX = currOffsetX
      self.lastAiY = currOffsetY
    },
    // 重新计算其他所有的画线距离
    recalculateAiByRuler() {
    
    
      const self = this
      for (let nameIndex = 0; nameIndex < Object.keys(this.aiLineStartMiddleInfo).length / 2; nameIndex++) {
    
    
        // 标尺信息不重新计算
        if (nameIndex === 0 || nameIndex === 5) {
    
    
          continue
        }
        const middleOffsetX = this.aiLineStartMiddleInfo[nameIndex+'middle']['offsetX']
        const middleOffsetY = this.aiLineStartMiddleInfo[nameIndex+'middle']['offsetY']
        const startOffsetX = this.aiLineStartMiddleInfo[nameIndex+'start']['offsetX']
        const startOffsetY = this.aiLineStartMiddleInfo[nameIndex+'start']['offsetY']
        const currDistance = Math.sqrt(( middleOffsetX - startOffsetX) ** 2 + (middleOffsetY - startOffsetY) ** 2)
        let currRealDistance = ( this.rulerRealDistance * 100 / this.rulerDistance * currDistance / 100).toFixed(1)
        const lineRef = self.aiDrawInfo['marker' + nameIndex + 'ai']
        lineRef.setOptions({
    
    'endLabel': currRealDistance + 'mm'})
      }
    },
    drawAiLine(color, x1, y1, x2, y2, index, tag, rulerRealDistance) {
    
    
      const self = this
      const nameIndex = self.aiIndex
      // 由于图片自适应,等比例缩放
      let imageHeight = $('#image-detail').height()
      let imageWidth = $('#image-detail .el-image__inner').width()
      const widthRatio = self.other.aiWidth / imageWidth
      const heightRatio = widthRatio
      x1 /= widthRatio
      y1 /= heightRatio
      x2 /= widthRatio
      y2 /= heightRatio
      this.markPointPlus(x1, y1, 'start', nameIndex)
      this.markPointPlus(x2, y2, 'middle', nameIndex)
      const dom31 = document.getElementById('marker' + nameIndex + 'ai' + "start")
      const dom32 = document.getElementById('marker' + nameIndex + 'ai' + "middle")
      let lineRef3 = new LeaderLine(dom31, dom32, {
    
    'color': color, 'path': 'straight'});
      lineRef3.show()
      self.aiDrawInfo['marker' + nameIndex + 'ai'] = lineRef3
      const currDistance = Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
      const currRealDistance = (rulerRealDistance * 100 / self.rulerDistance * currDistance / 100).toFixed(1)
      lineRef3.setOptions({
    
    'endLabel': currRealDistance + 'mm'})
      self.$emit('updateResult', {
    
    'index': index, 'tag': tag, 'value': currRealDistance})
    },
    drawByAi() {
    
    
      ...
    }
  }
}
</script>

<style lang="scss" scoped>
.line-block {
    
    
  height: 90vh;

  .one {
    
    
    display: flex;
    justify-content: space-around;
    // height: 100px;
  }

  .two {
    
    
    margin-top: 100px;
    display: flex;
    justify-content: space-around;
  }

  .iframe-block {
    
    
    margin-top: 50px;
  }

  .target {
    
    
    display: inline-block;
    background-color: #9ee7ea;
    padding: 12px;
  }

  .block-one {
    
    
    border: 1px solid blue;
    padding: 10px;
  }

  .block-two {
    
    
    border: 1px solid blue;
    padding: 10px;
  }

  .block-three {
    
    
    border: 1px solid blue;
    padding: 10px;
  }

  .block-four {
    
    
    border: 1px solid blue;
    padding: 10px;
  }
}
</style>

欢迎关注公众号 算法小生

猜你喜欢

转载自blog.csdn.net/SJshenjian/article/details/131735876