1、项目需求

项目中写好车站及图元的绘制方法,按照要求动态生成车站成品图。车站成品图涉及图元较多,如果每次打开页面动态绘制会占用较长时间,影响加载效率和用户体验。

2、解决方案

决定采用动态引入成品SVG图的方法。首先,使用绘制方法,生成车站svg代码,然后将浏览器中的svg代码复制粘贴出来,作为静态svg文件引入。

3、具体实现步骤

(1) vue中引入svg-sprite-loader,在vue.config.js中配置svg读取路径。

chainWebpack(config) {
    config.module
      .rule('icons')
      .test(/\.svg$/)
      .include.add([resolve('src/icons'), resolve('src/assets/jgsvg')])
      .end()
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]'
      })
      .end()
}

(2) 将成品车站图从浏览器控制台中复制出来,在网站中进行格式化,并查看格式化后的svg图形是否可以正常展示。

这里推荐两个网站:

在线代码格式化

svg在线制作编辑预览工具

将车站成品图代码放到src/assets/jgsvg目录下。

具体格式化后代码见下图。

(3) 引入方法,使用import引入svg文件

html:

<div class="editContainer_SVG"></div>

js:

import zhanchang from "@/assets/jgsvg/chang.svg"


  // 引入站场图
    importStation() {
      // 引入svg 
      let zhanchangSvg = zhanchang.content.replace(new RegExp("symbol", "gm"), "svg");
      let str = "width='100%' height='100%' ";
      // 添加svg属性
      let svgText = insertStr(zhanchangSvg, 5, str);
      $(".editContainer_SVG").append(svgText);
      this.$nextTick(() => {
        // 添加属性
        let self = this;
        // 这里必须指定已存在的元素 .editContainer_SVG 
        const pageSvg = d3.select(".editContainer_SVG #icon-TSRSzhanchang");
        this.pageSvg = pageSvg;
        let g =d3.select(".editContainer_SVG #icon-TSRSzhanchang >g");
        this.pageG = g;
        // 设置滚动及缩放限制
        this.svgZoom = d3.zoom()
          .scaleExtent(this.svgScaleExtent) // 添加放大限制
          .on("zoom", zoomed);
        this.pageSvg.call(this.svgZoom)
          .on("wheel", function () {
            d3.event.preventDefault(); // 放大倍数达到上下限时svg图形不随鼠标滚动上下移动
          })
          .on("dblclick.zoom", null)
          // 获取全体包,刷新全体包状态
        let allPakcData = this.$store.getters.packData;
        this.renderDom(allPakcData);
        // zoom 滚动及缩放方法 
        function zoomed() {
          let transforms = d3.event.transform;
          self.svgZoomTransform = transforms;
          // // //    $(".rectTipView").empty();
          self.rectTipFlag = false;
          self.pageG.attr("transform", transforms);
        }
      })
    }
/**
 * 在指定位置插入字符串
 * @param {*} soure 
 * @param {*} start 
 * @param {*} newStr 
 */
  export function insertStr(soure, start, newStr) {
    return soure.slice(0, start) + newStr + soure.slice(start)
  }

.editContainer_SVG所在的div为svg的容器。

使用import引入svg静态文件后,会改变svg原有的代码,

(1) 由symbol 标签包裹,需要替换symbol为svg;

(2) width,height属性消失,需要动态拼接width、height属性

(3) id会有所调整,编程icon_文件名,这里的需要对接下来代码中的指定元素进行修改。

(4) d3.select(".editContainer_SVG #icon-TSRSzhanchang") 这里一定要加原dom中已存在的元素 .editContainer_SVG,否则接下来设置的svg拖动、缩放无效。