好久没更了,近期开发遇到的需求,抽空梳理一下~
需求:实现一个复杂的拓扑图,图中元素的个数,以及各个参数内容是动态展示的。
于是让ui提供了对应的svg图片。
解决思路:使用iframe嵌入svg图片,运用D3.js修改其文本及样式。
html:
<iframe class="systemFrame" ref="systemFrame" :src="exportImg(topoSrc)" width="100%" height="100%" frameborder="0" ></iframe>
js:要从svg图里找到对应的元素id
onMounted(() => { let frameObj = systemFrame.value; if (frameObj.attachEvent) { frameObj.attachEvent("onload", function () {}); } else { frameObj.onload = function () { onIframeLoaded() loading.value = false }; } getTopo() })
const onIframeLoaded = () => {
const iframeWindow = systemFrame.value.contentWindow.document;
const svg = iframeWindow.getElementsByTagName('svg')
if(!svg.length) return
svg[0].style.background = '#242424'
// iframe加载完成后要进行的操作
var iframeSvg = systemFrame.value.contentDocument; //!!!!这里获取svgDom,一定要先获取父元素,才会展示子元素!!否则找不到
var svgObj = iframeSvg.getElementById("drawing"); //获取父元素下面id是drawing的子元素,接下来就可以对svgDom进行操作,绑定元素点击事件,改变元素的属性等等
let d3svg = d3.select(svgObj);
// 实现拓扑图缩放功能
svgPanZoom(svgObj, {
zoomEnabled: true,
panEnabled: false,
maxZoom: 2,
minZoom: 0.5,
preventMouseEventsDefault: false,
})
svgEdit(d3svg)
};
const svgEdit = (d3svg) => {
// 改变样式 流动的虚线
d3svg.select("#Right")
.style("animation", "path-animation " + 18 + "s")
.style("animation-timing-function", "linear")
.style("animation-iteration-count", "infinite");
// 循环各个元素 topoSrc是需要展示的元素个数
for(let i=1; i<topoSrc.value*1 + 1; i++) {
// 找到元素并移动位置
d3svg.selectAll('#power-'+ i).attr('transform', 'translate(-15)')
// 找到元素替换文本
d3svg.selectAll('#power-'+ i + ' .cls-20:nth-child(1)').text(topoData.value.packs[i-1].power + 'kW')
// 找到元素替换颜色
d3svg.select('#sys'+ i + ' .cls-24').style("fill", '#fff')
d3svg.select('#cu'+ i).style("fill", '#fff')
}
}