根据svg文本显示svg 并且支持鼠标划过显示器件名称 放大缩小拖动

整个页面Demo如下:

<template>
  <div id="home">
    <section id="top-section">
      <label for="">svg路径:</label>
      <el-input v-model="svgPath" size="small"></el-input>
      <el-button type="primary" size="small" @click="loadSvgData()"
        >加载</el-button
      >
    </section>
    <article>
      <div
        id="svg-container"
        style="width: 1300px; height: 700px; overflow: auto"
      ></div>
      <!-- svg元件鼠标悬浮提示框 -->
      <div
        id="svgTipBox"
        v-show="svgTipBoxVisible"
        v-bind:style="{
          left: svgTipBoxPositionX + 'px',
          top: svgTipBoxPositionY + 'px'
        }"
      >
        {{ svgTipBoxData }}
      </div>
    </article>
  </div>
</template>
 
<script>
import axios from 'axios';
// import Hammer from 'hammerjs'; //缩放比例
import svgPanZoom from 'svg-pan-zoom';
export default {
  name: 'Home',
  data() {
    return {
      url: '',
      srcList: [],
      svgPath: '/svg.svg', //svg文件路径  因为是本地测试需要把svg文件放在public里面
      svgData: '', //svg文件内容
      svgTipBoxData: '', //svg元件鼠标悬浮提示框内容
      svgTipBoxVisible: false, //svg元件鼠标悬浮提示框显示状态
      svgTipBoxPositionX: 0, //svg元件鼠标悬浮提示框x坐标
      svgTipBoxPositionY: 0 //svg元件鼠标悬浮提示框y坐标
    };
  },
  // 由于svg上添加的鼠标事件无法直接调用vue里的methods方法,需要将这些方法绑定到window下面,提供给外部调用
  async mounted() {
    // 将svgClick方法绑定到window下面,提供给外部调用
    window['handleClick'] = (evt, id) => {
      this.svgClick(evt, id);
    };
    // 将svgMouseOver方法绑定到window下面,提供给外部调用
    window['handleMouseOver'] = (evt, id) => {
      this.svgMouseOver(evt, id);
    };
    // 将svgMouseMove方法绑定到window下面,提供给外部调用ping 20.
    window['handleMouseMove'] = (evt, id) => {
      this.svgMouseMove(evt, id);
    };
    // 将svgMouseOut方法绑定到window下面,提供给外部调用
    window['handleMouseOut'] = (evt, id) => {
      this.svgMouseOut(evt, id);
    };
  },
  methods: {
    //加载按钮点击
    loadSvgData() {
      // ajax请求数据,并携带参数
      axios
        .get(this.svgPath)
        .then(
          (response) => {
            // console.log(response, 'res');
            // 将svg平面图显示在制定容器中
            let svgContainer = document.getElementById('svg-container');
            svgContainer.innerHTML = response.data;

            const svgElement = svgContainer.querySelector('svg'); // 查找 SVG 元素
            if (svgElement) {
              console.log(svgElement, 'svgElement');
              svgPanZoom(svgElement, {
                viewportSelector: '#svg-container',
                zoomEnabled: true,
                controlIconsEnabled: true,
                fit: true, // 自适应容器
                center: true //将 SVG 居中显示
              });
            }
            // 遍历svg里面的元素,自动添加鼠标事件
            this.addMouseEvent(svgContainer);
          },
          (err) => {
            console.log(err);
          }
        )
        .catch((error) => {
          console.log(error);
        });
    },

    // 遍历svg里面的元素,自动添加鼠标事件
    addMouseEvent(parent) {
      for (var i = 0; i < parent.childNodes.length; i++) {
        //循坏svg里面的元素
        var child = parent.childNodes[i];
        // 判断是不是g元素,并且具有id值,是的话,就添加鼠标事件
        if (
          child.tagName == 'g' &&
          child.id != null &&
          child.id.length > 0 &&
          child.id.indexOf('PD_') == 0
        ) {
          console.log(child.tagName + ':' + child.id);
          child.setAttribute('onclick', "handleClick(evt,'" + child.id + "')");
          child.setAttribute(
            'onmouseover',
            "handleMouseOver(evt,'" + child.id + "')"
          );
          child.setAttribute(
            'onmousemove',
            "handleMouseMove(evt,'" + child.id + "')"
          );
          child.setAttribute(
            'onmouseout',
            "handleMouseOut(evt,'" + child.id + "')"
          );
        }
        //继续递归遍历子元素
        this.addMouseEvent(child);
      }
    },
    // svg图元件点击事件
    svgClick(evt, id) {
      console.log(evt);
      alert(id);
    },
    // svg图元件鼠标移入事件
    svgMouseOver(evt, id) {
      // console.log('svgMouseOver');
      // console.log(evt);
      this.svgTipBoxData = id; //这里测试显示的开关的id
      this.svgTipBoxVisible = true;
    },
    // svg图元件鼠标移动事件
    svgMouseMove(evt, id) {
      // console.log('svgMouseMove');
      // console.log(evt);
      this.svgTipBoxPositionX = evt.pageX;
      this.svgTipBoxPositionY = evt.pageY - 50;
    },
    // svg图元件鼠标移出事件
    svgMouseOut(evt, id) {
      // console.log('svgMouseOut');
      // console.log(evt);
      this.svgTipBoxVisible = false;
    }
  }
};
</script>
 
<style scoped>
#home {
  padding: 22px 34px 22px 34px;
}
#top-section {
  width: 100%;
  margin-bottom: 20px;
}
#top-section label {
  font-size: 14px;
  line-height: 32px;
}
#top-section .el-input {
  margin-right: 20px;
  width: 200px;
}
#svgTipBox {
  position: absolute;
  padding: 10px;
  background: rgba(0, 0, 0, 0.8);
  color: red;
  border: 1px solid;
}
#svgControlBox {
  position: absolute;
}
/* #svg-container {
  width: 1000px;
  height: 800px;
} */
</style>
posted @ 2025-02-25 15:17  刘酸酸sour  阅读(30)  评论(0)    收藏  举报