VUE 外部SVG 文件导入与处理(D3.js)
Posted 姚家湾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 组件。
以上是关于VUE 外部SVG 文件导入与处理(D3.js)的主要内容,如果未能解决你的问题,请参考以下文章
使用 D3.js(IE、safari 和 chrome)创建 SVG 后,如何保存/导出 SVG 文件?