VUE 外部SVG 文件导入与处理(D3.js)

        在使用VUE 之前,我采用svidget,js 构建SVG的widget ,作为HMI 的UI 视图。但是到了VUE 中,怎么也不行,svidget.js 好像与vue 不兼容。于是转向了另一个强大的程序D3.js .虽然网络上有许多的介绍,但是在具体编程中,还有是遇到了许多坑。

1 D3.select 不起作用

        一开始发现 D3.select 找不到网页的元素,返回为空,即便是在mounted 函数中使用也是如此。最好发现要在mounted 函数中再添加一个nextTick才行。

mounted() {
   
    this.$nextTick(this.init)
 
  },


methode:{
init(){
  d3.select("#p10").text("HellO");
}}

2 d3.xml 不起作用

按照网络上的介绍,d3导入svg 外部文件的大致方式为:

   

d3.xml("..assets/valveV.svg").then(data=>{ 
d3.select(".p12").node().append(data.documentElement) ;
}
     

但是发现出错:

uncaught (in promise) typeerror: failed to execute 'fetch' on 'window': cannot convert to dictionary

       搞的晕头转向,后来发现d3.xml 应该是一个url 参数。既然是url 那么它指向那里呢?不要忘记的是VUE 服务和后台服务器是分离的。我们到底是从VUE 服务中取svg文件 还是从后台服务器上取svg 。事情变得复杂了。

后台服务器(nodeJS)取svg

methodes:{
init(){
    d3.xml("http://localhost:8000/img/valveV.svg").then(data=>{ 
     
      const width = 200;
      const height = 200;
      const svg = d3
        .select(".p12")
        .append("svg")
        .attr("width", width)
        .attr("height", height);
      svg.node().append(data.documentElement) 
    })
     }
}

vue 服务器取svg

        如果svg 放置在vue 服务器上,要将svg 文件放置在根目录的public 下面。但是d3.xml中要写成d3.xml(" /2svg "),不能写成 /public/2.xml 。

  methods: {
     init(){
    d3.xml("/2.svg").then(data=>{ 
 
      const svg = d3
        .select(".svg")
        .append("svg")
        .attr("width", this.Options.width)
        .attr("height", this.Options.height);
      svg.node().append(data.documentElement) 
    })
     },

    也不能写在 /assets,/static 目录中。

3 基于d3 的svg widget

          这里我们没有采纳在svg 内部编写程序,构建svg  widget 的方法,而是使用d3 来管理svg 元素。具体的方法是在svg 中的元素添加id ,通过d3.select 选择rect1 改变rect1 的颜色。

最后的VUE 组件是这样的 :

<template>
<div>
<div class="svg" ref="object"> 
<b-button variant="info" @click="clickChangeColor()">ChangeColor</b-button>

</div>
</div>
</template>
<script>
 

import * as d3 from 'd3';
export default {
  name: 'HMI_d3svg',
  data() {
    return { 
       Name:"",
        ID:0,
        Options:{
          Size:"400px",
          Position:{
            X:"400px",
            Y:"20px"
          },       
      width:"500px",
      height:"200px",
      color:"yellow" 
        }    
    };
  },
 mounted() {
   
    this.$nextTick(this.init)

  },
   methods: {
     init(){
    d3.xml("http://localhost:8000/img/2.svg").then(data=>{ 
     this.$refs.object.style.top=this.Options.Position.Y;
     this.$refs.object.style.left=this.Options.Position.X;
      const svg = d3
        .select(".svg")
        .append("svg")
        .attr("width", this.Options.width)
        .attr("height", this.Options.height);
      svg.node().append(data.documentElement) 
    })
     },
 
 clickChangeColor(){
   if (this.color=="red"){
        this.color="yellow";
        d3.select("#rect1").attr("fill","yellow");
   }  else {
        this.color="red";
        d3.select("#rect1").attr("fill","red");
   } 
 },
}  
}  
</script>
<style scoped>
.svg {
  position:absolute;
}      
</style>

使用svg 工具

       顺便提一句,我使用inkscape 开源svg 工具设计svg 图形。

结论

        到此为止,我们可以使用vue 来设计svg widget 了。作为HMI 的UI 组件。

Supongo que te gusta

Origin blog.csdn.net/yaojiawan/article/details/119729387
Recomendado
Clasificación