vue+D3项目拓扑图缩放,拖拽,保存布局等
注意:vue+D3里面的当数据更新的时候,需要先将之前的数据绘画的点清除 (选择所有的点清除,才可以重新绘画),否则将会重新绘画两次,因为之前的数据渲染的视图并没有清除,这该d3和query功能差不多 ,都是原生js的一些封装,所以不会像那些表格插件一个,选择的时候,初始化一下。故这里需要手动初始化。找了很多资料对vue+D3实现的这些拓扑图的代码比较,getLinksData:f...
·
注意:vue+D3里面的当数据更新的时候,需要先将之前的数据绘画的点清除 (选择所有的点清除,才可以重新绘画),否则将会重新绘画两次,因为之前的数据渲染的视图并没有清除,这该d3和query功能差不多 ,都是原生js的一些封装,所以不会像那些表格插件一个,选择的时候,初始化一下。故这里需要手动初始化。
找了很多资料对vue+D3实现的这些拓扑图的代码比较,
getLinksData:function(nodesData,obj ){ //获取链路的信息数据集合
this.linksData=[];
let that=this;
this.$ajax.get('/topology/links'+'?token='+this.token)
.then(res => {
if(res.status==200 && res.data.status==0){
that.linksData=res.data.data;
// that.backupLink=res.data.data;
this.dealForm(obj,nodesData,that.linksData)
}
}).catch(e => {console.log(e)})
},
setTopo:function(nodesData,linksData){//设置拓扑图的展示
d3.select('svg').select('g').remove()
var width = 890,
height = 470;
var text_dx = -20;
var text_dy = 20;
var img_w=16,img_h=16;
var radius=16;
linksData.some(function(v, i) {
nodesData.some(function(w, j) {
if (v.source_node == w.node.id) {
v.source_val= w;
}
if (v.target_node == w.node.id) {
v.target_val= w;
}
});
v.index = ++i;
});
let that=this
var linkForce=d3.forceLink(linksData)
.id(function(d){})
let simulation = d3.forceSimulation()
.nodes(nodesData)
let centerForce = d3.forceCenter(width / 2, height / 2);
let chargeForce = d3.forceManyBody()
simulation
.force('chargeForce', chargeForce)
.force('centerForce', centerForce)
.force('links', linkForce)
simulation.on('tick', tickActions)
var svg = d3.select('svg')
.attr('width',width)
.attr('height',height)
//
var g = svg.append('g');
var nodes_text = g.selectAll('.node_text')
.data(nodesData)
.enter()
.append('text')
.attr('class','font')
.text(function(d){
return d.node.name
})
var links_text=g.selectAll('.link_text')
.data(linksData)
.enter()
.append('text')
.attr('class','links_text')
.text(function(d){
return d.bandwidth
})
// .attr('class', 'link')
let link = g.append('g')
.attr('class', 'link')
.selectAll('line')
.data(linksData)
.enter()
.append('line')
.style('stroke-width', linkWidth)
.style('stroke', linkColour)
.attr('class',function(d){//对数据进行处理
if(typeof d.speedColor =='undefined'){ //流量的显示不存在的时候 这个时候关闭 返回默认的颜色
return linkColour;
}else { //当存在 流量的时候 显示流量
return d.speedColor;
}
})
.on('click',function(d){
var cls=document.getElementsByTagName('line');
for (let index=0;index<cls.length;index++) {
cls[index].style.strokeWidth='2';
}
this.style.strokeWidth='8';
let obj={}
if(d.type==='link'){
obj={
id:d.id,
type:'link'
}
}else{
obj={
id:d.id,
type:'cloun'
}
}
that.$emit('sendlink',true)
that.bus.$emit('sendlink',obj);
that.$store.commit('sendLink',obj);
})
function linkWidth(d){
return 2;
}
function linkColour(d){
if(d.status=='UP'){
return '#6BC7E2'
}else if(d.status=='DOWN'){
return '#444242'
}else if(d.status=='running'){
return '#9254DE';
}
}
// function baseColor(d){
// if(d.status=='UP'){
// d.color='linkUP'
// }else if(d.status=='DOWN'){
// d.color='linkDOWN'
//
// }else if(d.status=='running'){
// d.color='linkRun'
// }
// return d.color
// }
let node = g.append('g')
.attr('class', 'nodes')
.selectAll('circle')
.data(nodesData)
.enter()
.append('image')
.attr('r', radius)
.attr('xlink:href',nodeTypeImage)
.attr('height',img_h)
.attr('width',img_w)
.attr('x',function(d){
return d.x-img_w/2
})
.attr('y',function(d){
return d.y-img_h/2
})
// 节点的拖拽
let dragHandler = d3.drag()
.on('start', dragStart)
.on('drag', dragDrag)
.on('end', dragEnd)
dragHandler(node)
node.on('click',function(d){
that.$store.commit('newAuthor',d.node.id) //向数据仓库传值
// //向父节点传值
that.$emit('parentDelta',true)
that.bus.$emit('sendNodeID',d.node.id);
that.nodeId=d.node.id;
})
//节点的缩放
function zoomActions () {
g.attr('transform', d3.event.transform)
}
let zoomHandler = d3.zoom()
.on('zoom', zoomActions)
zoomHandler(svg)
d3.select('#big').on('click',function(d){
zoomHandler.scaleBy(svg, 1.1); // 执行该方法后 会触发zoomHandler事件
let tran = d3.zoomTransform(svg.node());
})
d3.select('#small').on('click',function(){
zoomHandler.scaleBy(svg, 0.9); // 执行该方法后 会触发zoomHandler事件
let tran = d3.zoomTransform(svg.node());
})
// let newData=[];//用来保存拖拽后的所有的节点
let newObj={};//保存拖拽后的每个节点数据
function tickActions () {
node.attr("x", function(d) { return d.x-img_w/2; })
.attr("y", function(d) { return d.y-img_h/2; });
// nodesData.forEach((d,i) => { //设置边界
// d.x= d.x - img_w/2 < 0 ? img_w/2 : d.x;
// d.y=d.y - img_h/2 < 0? img_h/2 : d.y;
// });
link.attr("x1", function(d) {
if(d.source_val){
return d.source_val.x;
}
})
.attr("y1", function(d) {
if(d.source_val){
return d.source_val.y;
}
})
.attr("x2", function(d) {
if(d.target_val){
return d.target_val.x;
}
})
.attr("y2", function(d) {
if(d.target_val){
return d.target_val.y;
}
})
nodes_text.attr('x',function(d){d.fx=d.x;return d.x-12})
.attr("y", function(d) { d.fy=d.y;return d.y-12 });
links_text.attr("x", function(d) {
if(d.source_val && d.target_val){
return (d.source_val.x+d.target_val.x)/2;
}
})
.attr("y", function(d) {
if(d.source_val && d.target_val){
return (d.source_val.y+d.target_val.y)/2;
}
})
}
function nodeTypeImage(nodes){
if(nodes.type==='node'){
return require('../../../assets/images/newTopo/node.png')
}else if(nodes.type==='阿里云'){
return require('../../../assets/images/newTopo/ali.png')
}else if(nodes.type==='腾讯云'){
return require('../../../assets/images/newTopo/tencent.png')
}else if(nodes.type==='华为云'){
return require('../../../assets/images/newTopo/huawei.png')
}else if(nodes.type==='UCloud'){
return require('../../../assets/images/newTopo/ucloud.png')
}else{
return require('../../../assets/images/newTopo/error.png')
}
}
function dragStart (d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart()
d.fx = d.x
d.fy = d.y
}
// make sure you can't drag the circle outside the box
function dragDrag (d) {
d.fx = d3.event.x
d.fy = d3.event.y
}
function dragEnd (d) {
if (!d3.event.active) simulation.alphaTarget(0)
d.fx = null
d.fy = null
newObj={
id:d.id,
x:d.x,
y:d.y
}
that.saveData.push(newObj);
}
},
以上代码就是将数据绘画到组件内渲染的代码
更多推荐
已为社区贡献1条内容
所有评论(0)