两点之间连线 svg

效果图

 

 思路:

  1.通过svg绘画出 线条 和 箭头,通过 元素在页面中的位置 父级所在页面中的位置  的差值计算出 箭头和线的 起始坐标及结束坐标,

页面滚动则  更新元素位置并且重新绘画

核心源码:

<template>
  <svg class="line-svg" xmlns="http://www.w3.org/2000/svg" version="1.1" :key="updeTime">
    <defs>
      <marker
        id="arrow"
        markerUnits="strokeWidth"
        markerWidth="10"
        markerHeight="10"
        viewBox="0 0 10 10"
        refX="10"
        refY="6"
        orient="auto"
      >
        <path d="M2,2 L10,6 L2,10 L2,2" style="fill:currentColor" />
      </marker>
    </defs>

    <line
      :x1="item.x1"
      :y1="item.y1"
      :x2="item.x2"
      :y2="item.y2"
      stroke="currentColor"
      marker-end="url(#arrow)"
      stroke-width="1.45"
      v-for="(item, index) in svgArr"
      :key="index"
    ></line>
  </svg>
</template>

<script>
export default {
  name: 'ConnectLine',
  props: {
    lineArr: {
      type: Array,
      default: () => [
        //  {
        //     sourceIndex: index,
        //     targetIndex: index,
        //   }
      ]
    }
  },
  data() {
    return {
      updeTime: new Date().getTime(),
      svgArr: [],
      color: this.$store.state.setting.color
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.parDom = document.getElementsByClassName('newBuild_mapping_table')[0]
      this.initConnect()
    })
  },
  methods: {
    //连线
    initConnect() {
      this.$nextTick(() => {
        this.updeTime = new Date().getTime() //更新组件
        this.svgArr = []
        let sourceEl = Array.from(document.querySelectorAll('.yuan')) //左边的圆点
        let targetEl = Array.from(document.querySelectorAll('.yuan2')) //右边的圆点
        this.lineArr.forEach(item => {
          if (item.sourceIndex !== '' && item.targetIndex !== '') {
            let el1 = sourceEl[item.sourceIndex]
            let el2 = targetEl[item.targetIndex]
            this.$nextTick(() => {
              el1.classList.add('action')
              el2.classList.add('action')

              this.connect(el1, el2)
            })
          }
        })
      })
    },
    connect(el1, el2) {
      this.svgArr.push({
        x1:
          el1.getBoundingClientRect().left -
          this.parDom.getBoundingClientRect().left +
          el1.getBoundingClientRect().width,
        y1: el1.getBoundingClientRect().top + el1.offsetHeight / 2 - this.parDom.getBoundingClientRect().top,
        x2: el2.getBoundingClientRect().left - this.parDom.getBoundingClientRect().left,
        y2: el2.getBoundingClientRect().top + el2.offsetHeight / 2 - this.parDom.getBoundingClientRect().top
      })
    }
  }
}
</script>

<style scoped lang="less">
.line-svg {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 3;
  width: 100%;
  height: 100%;
  pointer-events: none;
  color: @b06-color;
  opacity: 0.6;
}
</style>

 

vue 插件 LeaderLine 也可以实现以上功能

 

posted @ 2022-07-28 17:45  混名汪小星  阅读(905)  评论(0编辑  收藏  举报