注意: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);
			    }
			},
以上代码就是将数据绘画到组件内渲染的代码

 

 

Logo

前往低代码交流专区

更多推荐