【发布时间】:2018-07-17 20:44:20
【问题描述】:
我正在尝试根据 Id 而不是 codepen 中的索引链接节点,我不知道该怎么做。
以下作品:
var links = [{ source: 0, target: 1 }];
但如果我根据名称创建链接,它不会创建任何链接。
var links = [{ source: "FH" , target: "TP" }];
【问题讨论】:
标签: javascript d3.js
我正在尝试根据 Id 而不是 codepen 中的索引链接节点,我不知道该怎么做。
以下作品:
var links = [{ source: 0, target: 1 }];
但如果我根据名称创建链接,它不会创建任何链接。
var links = [{ source: "FH" , target: "TP" }];
【问题讨论】:
标签: javascript d3.js
D3v3 强制布局不支持链接中的命名节点。如果您想在不需要任何额外工作的情况下使用它们,我建议您使用 d3v4 或 v5。
但是,与REEE 的回答一样,您可以通过更改代码并保留 v3.0 来达到相同的效果。我没有更改刻度,而是在启动数组之前更改 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,或下面的一个 sn-p(我已将您的节点数组移动到它自己的变量中 - 是的,它被称为节点,稍后会被覆盖):
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>
【讨论】:
var obj ={}。既然你称它为map,我们期待的是一张真实的地图,比如var map = new Map() 或var map = d3.map()。顺便说一句,使用真实的地图比使用对象要快,但是这里的数据太短了,可能没有区别。
你可以这样做: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 函数中通过数组过滤是否是个好主意,因为如果生成大量节点,它可能会导致性能问题。 tick 函数被调用了很多。
【讨论】: