我试图基于Id而不是基于此codepen中的索引来链接节点,所以我不知道该怎么做。
以下作品:
var links = [{ source: 0, target: 1 }];
但是,如果我基于名称创建链接,则不会创建任何链接。
var links = [{ source: "FH" , target: "TP" }];
答案 0 :(得分:5)
D3v3强制布局不支持链接中的命名节点。如果您想使用它们而不需要任何额外的工作,我建议使用d3v4或v5。
但是,与REEE的答案一样,您可以通过更改代码并保留v3来达到相同的效果。我没有更改刻度,而是在启动数组之前更改了link
数组:
var obj = {}
nodes.forEach(function(d,i){
obj[d.id] = i; // create an object to look up a node's index by id
})
links.forEach(function(d) {
d.source = obj[d.source]; // look up the index of source
d.target = obj[d.target]; // look up the index of target
})
这是一个分叉的plunkr或下面的代码片段(我将您的节点数组移到了自己的变量中-是的,它称为节点,以后会被覆盖):
var width = 500,
height = 200;
var fill = d3.scale.category20();
var links = [{ source: "FH", target: "TP" }];
var nodes = [
{ id: "FH", x: 100, y: 110 },
{ id: "TP", x: 200, y: 110 },
{ id: "GW", x: 200, y: 110 },
{ id: "DB", x: 100, y: 110 }
]
var obj = {}
nodes.forEach(function(d,i){
obj[d.id] = i;
})
links.forEach(function(d) {
d.source = obj[d.source];
d.target = obj[d.target];
})
var force = d3.layout
.force()
.size([width, height])
.nodes(nodes)
.links(links)
.linkDistance(150)
.charge(-500)
.on("tick", tick);
var svg = d3
.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var arrows = svg
.append("svg:defs")
.selectAll("marker")
.data(["arrow"])
.enter()
.append("marker")
.attr("id", String)
.attr("viewBox", "0 -5 10 10")
.attr("refX", 15)
.attr("refY", -1.5)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("path")
.attr("d", "M0,-5L10,0L0,5");
svg
.append("rect")
.attr("width", width)
.attr("height", height);
var nodes = force.nodes(),
links = force.links(),
node = svg.selectAll(".node"),
link = svg.selectAll(".link");
restart();
function tick() {
link.attr("d", function(d) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy);
return (
"M" +
d.source.x +
"," +
d.source.y +
"A" +
dr +
"," +
dr +
" 0 0,1 " +
d.target.x +
"," +
d.target.y
);
});
node.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
}
function restart() {
node = node.data(nodes);
node
.enter()
.insert("g")
.attr("class", "node")
.call(force.drag);
node
.append("image")
.attr("xlink:href", "https://github.com/favicon.ico")
.attr("x", -8)
.attr("y", -8)
.attr("width", 16)
.attr("height", 16);
node
.append("text")
.attr("dx", 12)
.attr("dy", ".35em")
.text(function(d) {
return d.id;
});
node.exit().remove();
link = link.data(links);
link
.enter()
.append("path")
.attr("class", "link")
.attr("marker-end", "url(#arrow)");
link.exit().remove();
force.start();
}
#nodeConsole {
width: 80%;
height: 1px;
font-family: courier new;
padding: 1px;
border: 3px solid gray;
margin-top: 1px;
overflow: autao;
}
#linkedNodes {
width: 80%;
font-family: courier new;
padding: 10px;
}
#srcNodes {
width: 40%;
font-family: courier new;
padding: 8px;
}
#targetNodes {
width: 40%;
font-family: courier new;
padding: 8px;
}
rect {
fill: none;
pointer-events: all;
}
.node {
fill: #000;
}
.cursor {
fill: none;
stroke: brown;
pointer-events: none;
}
.link {
stroke: #999;
}
.node text {
pointer-events: none;
font: 10px sans-serif;
}
path.link {
fill: none;
stroke: #666;
stroke-width: 1.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
答案 1 :(得分:1)
您可以这样操作:https://codepen.io/anon/pen/yqJoje?editors=0011
我基本上过滤节点数组,以查找与目标和源有关的x和y数据,然后将它们分配给一个值,以供您进行路径分配。相关代码在这里:
function tick() {
link.attr("d", function(d) {
var curData = {
target: nodes.filter(function (n) {
if (n.id == d.target) {
return { x: d.x, y: d.y };
}
})[0],
source: nodes.filter(function (n) {
if (n.id == d.source) {
return { x: d.x, y: d.y };
}
})[0]
};
...
...
}
注意:不确定在tick函数中通过数组过滤是否是一个好主意,因为如果生成大量节点,可能会导致性能下降。滴答功能被称为很多。