我正在尝试在 d3.js 中构建一个有向力图,它上面有一个点击监听器,可以更改基础数据并重绘图形。我相信我正在遵循 Bostock 先生的更新模式,但我遇到的问题是,当我运行由点击侦听器触发的更新时,节点会从屏幕底部消失,留下链接和标签。
此更新似乎正在运行,更新现有节点(在这种情况下将它们变为绿色)然后忽略“进入”和“退出”部分(这是所需的行为)然后点击将节点发送到南方的 tick() 函数。
我可以通过删除节点上的“g”标签来实现这个工作,从而将标签和节点解耦,这显然是不可取的。
我不禁觉得我错过了一些明显的东西!或者也许我应该以不同的方式解决这个问题?
这是代码:
var width = 960,
height = 500,
links,
nodes,
root;
var force = d3.layout.force()
.size([width, height])
.charge(-200)
.linkDistance(50)
.on("tick", tick);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var link = svg.selectAll(".link"),
node = svg.selectAll(".node");
d3.json("test.json", function(json) {
root = json;
update();
});
function update() {
nodes = root.nodes
links = root.links
// Restart the force layout.
force
.nodes(nodes)
.links(links)
.start();
svg.append("svg:defs").append("marker")
.attr("id", "end")
.attr("refX", 15)
.attr("refY", 2)
.attr("markerWidth", 6)
.attr("markerHeight", 4)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M 0,0 V 4 L8,2 Z");
// Update the links…
//link = link.data(links, function(d) { return d.target.name; });
link = link.data(links)
// Exit any old links.
link.exit().remove();
// Enter any new links.
link.enter().insert("svg:line", ".node")
.attr("class", "link")
.attr("marker-end", "url(#end)")
.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; });
// Update the nodes…
node = svg.selectAll("g").select(".node").data(nodes, function(d) { return d.name; });
node.style("fill", "green")
// Exit any old nodes.
node.exit().remove();
// Enter any new nodes.
node.enter().append("g")
.append("svg:circle")
.attr("class", "node")
.attr("id", function(d) {return "node" + d.index; })
.attr("r", 12)
.style("fill", "#BBB")
.on("click", click)
.call(force.drag);
node.append("svg:text")
.attr("dx", 16)
.attr("dy", ".15em")
.attr("class", "nodelabel")
.text(function(d) { return d.name });
}
function tick() {
link.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; });
node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
}
function click(d) {
if (!d3.event.defaultPrevented) {
// DO ANYTHING
update()
}
}
test.json 的内容是:
{
"nodes": [
{"name" : "John"},
{"name" : "Alison"},
{"name" : "Phil"},
{"name" : "Jim"},
{"name" : "Jane"},
{"name" : "Mary"},
{"name" : "Joe"}
],
"links": [
{"source": 1, "target": 0},
{"source": 2, "target": 0},
{"source": 3, "target": 0},
{"source": 4, "target": 0},
{"source": 5, "target": 1},
{"source": 6, "target": 1}
]
}