当我单击一个节点时,我希望向其添加一个新节点。它们都应该都有标签(我正在尝试建立同义词库可视化文件。)
我是D3的新手,如果您需要更详细地说明事情,我深表歉意。
到目前为止,这是我的代码:
var width = 960;
var height = 500;
var force = d3.layout.force()
.gravity(0.05)
.distance(100)
.charge(-100)
.size([width, height])
.nodes([{ "name": "One", "group": 1 }])
.start();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var nodes = force.nodes();
var links = force.links();
var link = svg.selectAll(".link")
.data(links)
.enter().append("line")
.attr("class", "link");
var node = svg.selectAll(".node")
.data(force.nodes())
.enter().append("g")
.attr("class", "node")
.call(force.drag);
node.append("circle")
.attr("r", 10)
.on("mousedown", onClick);
node.append("text")
.attr("dx", 12)
.attr("dy", ".35em")
.text(d => d.name);
force.on("tick", function() {
link.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
node.attr("transform", d => {
// d.x & d.y are NaN for new nodes
return "translate(" + d.x + "," + d.y + ")";
});
});
restart();
function restart() {
node = node.data(nodes);
node.enter().append("g")
.attr("class", "node")
.call(force.drag);
node.append("circle")
.attr("r", 10)
.on("mousedown", onClick);
node.append("text")
.attr("dx", 12)
.attr("dy", ".35em")
.text(d => d.name);
node.exit().remove();
link = link.data(links);
}
function onClick(clicked_node) {
console.log("click!");
console.log(clicked_node);
var new_node = { name: "Test", group: 2 };
nodes.push(new_node);
// Has x & y set to NaN after adding
links.push({ source: clicked_node, target: new_node });
restart();
}
当我单击第一个节点时,导致该节点
{ name: "Test", group: 2 };
要添加的内容,D3会引发错误
node.attr("transform", d => {
// d.x & d.y are NaN for new nodes
return "translate(" + d.x + "," + d.y + ")";
});
因为此新节点的d.x
和d.y
是NaN
。
我尝试明确设置它们:
{ name: "Test", group: 2, x: clicked_node.y, y: clicked_node.y };
但是我得到了同样的错误。在检查器中,将此节点添加到屏幕后,x
和y
的值将变成px
和py
的值!
我不明白为什么会这样。
答案 0 :(得分:2)
您缺少一行代码。添加新节点后,您需要重新启动d3
的仿真以计算其位置:
function restart() {
node = node.data(nodes);
node.enter().append("g")
.attr("class", "node")
.call(force.drag);
node.append("circle")
.attr("r", 10)
.on("mousedown", onClick);
node.append("text")
.attr("dx", 12)
.attr("dy", ".35em")
.text(d => d.name);
node.exit().remove();
link = link.data(links);
force.start(); //<-- start simulation
}
运行代码:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@3.5.17" data-semver="3.5.17" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.js"></script>
</head>
<body>
<script>
var width = 960;
var height = 500;
var force = d3.layout.force()
.gravity(0.05)
.distance(100)
.charge(-100)
.size([width, height])
.nodes([{ "name": "One", "group": 1 }])
.start();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var nodes = force.nodes();
var links = force.links();
var link = svg.selectAll(".link")
.data(links)
.enter().append("line")
.attr("class", "link");
var node = svg.selectAll(".node")
.data(force.nodes())
.enter().append("g")
.attr("class", "node")
.call(force.drag);
node.append("circle")
.attr("r", 10)
.on("mousedown", onClick);
node.append("text")
.attr("dx", 12)
.attr("dy", ".35em")
.text(d => d.name);
force.on("tick", function() {
link.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
node.attr("transform", d => {
// d.x & d.y are NaN for new nodes
return "translate(" + d.x + "," + d.y + ")";
});
});
restart();
function restart() {
node = node.data(nodes);
node.enter().append("g")
.attr("class", "node")
.call(force.drag);
node.append("circle")
.attr("r", 10)
.on("mousedown", onClick);
node.append("text")
.attr("dx", 12)
.attr("dy", ".35em")
.text(d => d.name);
node.exit().remove();
link = link.data(links);
force.start();
}
function onClick(clicked_node) {
console.log("click!");
console.log(clicked_node);
var new_node = { name: "Test", group: 2 };
nodes.push(new_node);
// Has x & y set to NaN after adding
links.push({ source: clicked_node, target: new_node });
restart();
}
</script>
</body>
</html>