d3.js实现双击删除节点并删除节点上的文字

最近项目遇到一个问题:删除节点,节点上的文字却无法删除。

经过F12的调试,我发现原来自己写的节点、连线、文字分别包裹在不同的g标签内。

于是出现了两种解决方案:

(1)把文字依附在节点上

(2)选中节点的时候遍历文字确保是哪个文字和该节点是对应的

我个人认为第一种方案是最优化的,我也推荐大家遇到这个问题采用第一种方案。 

但是我项目之前写的结构就这样了,如果现在改的话,需要改的代码太多,于是我采用第二种方案。

废话之后,干货奉上

以下是我写的一个demo:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>双击删除节点</title>
		<script src="http://d3js.org/d3.v3.min.js"></script>  
	</head>
	<body>
		<script>
			var width = 1366;
			var height = 768;
			var img_w = 77;
			var img_h = 80;
        	var radius = 30;
			var svg = d3.select("body")
						.append("svg")
						.attr("width",width)
						.attr("height",height);
   			d3.json("json/song.json",function(error,data){
   				if(error){
   					return console.log(error);
   				}
   			var dataset = data;
   			console.log(dataset);
   			
   			var force = d3.layout.force()
   						  .nodes(dataset.nodes)
   						  .links(dataset.links)
   						  .size([width,height])
   						  .linkDistance(100)
   						  .charge(-1500)
   						  .start();
   						  
   			var links = svg.selectAll("line")
   						   .data(dataset.links)
   						   .enter()
   						   .append("line")
   						   .attr("class","lines")
   						   .attr("style","stroke: #CCCCCC; stroke-width: 2;");

			var nodes = svg.selectAll("circle")
						   .data(dataset.nodes)
						   .enter()
						   .append("circle")
						   .attr("r",radius)
						   .attr("class","nodes")
						   .attr("fill","pink")
						   .on("dblclick",function(d){
						   		//双击节点删除,获取选中节点的在json中的name的值
						   		d3.select(this).remove();
						   		var clickNodeName = d.name;//点击节点的名字
						   		d3.selectAll(".nodetext").each(function(d,i){
						   			var temp = d.name;
						   			if(temp==clickNodeName){
//						   				alert("相等");
						   				d3.select(this).remove();
						   			}
						   		});
						   		d3.selectAll(".lines").each(function(e){
						   			if(e.source===d||e.target===d){
						   				d3.select(this).remove();
						   			}
						   		})
						   })
                       	   .on("mouseout",function(d,i){
                       			nodes.style("stroke",function(edge){
                       				if(edge.source===d){
                       					return "#CCCCCC";
                       				}
                       			});
                                links.style("stroke","#CCCCCC");
	                       })
						   .call(force.drag);
					   
			var text_dx = -20;
			var text_dy = 20;
			console.log("x:"+text_dx);
			console.log("y:"+text_dy);
			
			var nodes_text = svg.selectAll(".nodetext")
							.data(dataset.nodes)
							.enter()
							.append("text")
							.attr("class","nodetext")
							.attr("dy",".35em")
							.attr("text-anchor","middle")
						    .text(function(d) { return d.name; });
			force.on("tick", function() {  
				
				links.attr("x1", function(d) { return d.source.x; })
				     .attr("y1", function(d) { return d.source.y; })  
				     .attr("x2", function(d) { return d.target.x; })  
				     .attr("y2", function(d) { return d.target.y; });
				
				nodes.attr("cx", function(d) { return d.x; })  
				     .attr("cy", function(d) { return d.y; });  
				
				nodes_text.attr("dx", function(d) { return d.x-img_w/4; })
				     	 .attr("dy", function(d) { return d.y+5; }); 
			});  
   		});
		</script>
	</body>
</html>

json文件如下:

{
   				"nodes":[
   						 {"name":"人物1","group":3,"img":"img/1.jpg"},
   						 {"name":"人物2","group":3,"img":"img/2.jpg"},  
						 {"name":"人物3","group":3,"img":"img/3.jpg"},  
						 {"name":"人物4","group":3,"img":"img/4.jpg"},
						 {"name":"人物5","group":3,"img":"img/5.jpg"},
						 {"name":"人物6","group":2,"img":"img/6.jpg"},  
   						 {"name":"人物7","group":2,"img":"img/7.jpg"},  
						 {"name":"人物8","group":2,"img":"img/8.jpg"},  
						 {"name":"人物9","group":2,"img":"img/9.jpg"},
						 {"name":"人物10","group":2,"img":"img/10.jpg"},
						 {"name":"人物11","group":1,"img":"img/11.jpg"},
						 {"name":"人物12","group":1,"img":"img/12.jpg"},
						 {"name":"人物13","group":1,"img":"img/13.jpg"},
						 {"name":"人物14","group":1,"img":"img/14.jpg"},
						 {"name":"人物15","group":1,"img":"img/15.jpg"},
						 {"name":"人物16","group":1,"img":"img/16.jpg"}],
   				"links":[{"source":0,"target":1,"relation":"\ue900 \ue904 \ue908 \ue9a1"},  
				         {"source":0,"target":2,"relation":"关系一"},
				         {"source":0,"target":3,"relation":"关系二"},
				         {"source":0,"target":4,"relation":"\ue909"},
				         {"source":5,"target":6,"relation":"\ue9a1"},  
				         {"source":5,"target":7,"relation":"\ue9a2"},
				         {"source":5,"target":8,"relation":"\ue9a3"},
				         {"source":5,"target":9,"relation":"\ue9ad"}, 
				         {"source":10,"target":11,"relation":"\ue9c1"},
				         {"source":10,"target":12,"relation":"\ue9c3"},
				         {"source":10,"target":13,"relation":"\ue9dd"},
				         {"source":10,"target":14,"relation":"\ue9fd"},
				         {"source":10,"target":15,"relation":"\ue9ed"},
				         {"source":10,"target":11,"relation":"\ue91d"},
				         {"source":0,"target":5,"relation":"\ue93d"},
				         {"source":5,"target":10,"relation":"\ue95d"},
				         {"source":10,"target":0,"relation":"\ue97d"}
				       ] 
   			}

测试效果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值