最近项目遇到一个问题:删除节点,节点上的文字却无法删除。
经过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"}
]
}
测试效果如下: