我在获取与 D3.js 一起使用的东西时遇到了一些麻烦。也就是说,我正在尝试使用 http://bl.ocks.org/mbostock/1021953 中的基本代码来制作一棵节点树。 .
我将其切换为内联加载数据,而不是从文件加载,因为我将它与 Rails 应用程序一起使用,并且不希望有重复的信息。我切换了线路,以便您可以看到我的数据的格式。
无论如何,这是我的大部分代码:
<%= javascript_tag do %>
var nodes = [{"title":"Duncan's Death","id":"265"},{"title":"Nature Thrown Off","id":"266"},{"title":"Cows Dead","id":"267"},{"title":"Weather Bad","id":"268"},{"title":"Lighting kills man","id":"269"},{"title":"Macbeth's Rise","id":"270"}];
var links = [{"source":"265","target":"266","weight":"1"},{"source":"266","target":"267","weight":"1"},{"source":"266","target":"268","weight":"1"},{"source":"268","target":"269","weight":"1"}];
var firstelement = +links[0].source;
links.forEach(function(l) {
l.source = +l.source;
l.source = l.source-firstelement;
l.target = +l.target
l.target = l.target-firstelement;
});
var width = 960,
height = 500;
var color = d3.scale.category20();
var force = d3.layout.force()
.charge(-1000)
.linkDistance(300)
.size([width, height]);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
force
.nodes(nodes)
.links(links)
.start();
var link = svg.selectAll(".link")
.data(links)
.enter().append("line")
.attr("class", "link")
.style("stroke-width", function(d) { return Math.sqrt(d.weight); });
var node = svg.selectAll(".node")
.data(nodes)
.enter().append("g")
.attr("class", "node")
.call(force.drag);
node.append("circle")
.attr("class", "circle_node")
.attr("r", 50)
.style("fill", function(d) { return color(d.id); })
node.append("title")
.text(function(d) { return d.title; });
node.append("text")
.attr("x", function(d) { return d.x; } )
.attr("y", function(d) { return d.y; })
.text(function(d) { return d.title; });
force.on("tick", function() {
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("x", function(a) { return a.x; })
.attr("y", function(a) { return a.y; });
});
<% end %>
这似乎对我有用,但我似乎可以管理它。链接有效,但节点全部保留在左上角。我尝试直接输入圆圈并将文本附加到其中(靠近我上面列出的源代码),但是虽然圆圈行为正常,但它不显示文本。我希望标题位于节点的中心。
更一般地说,我对它的工作原理感到有点困惑。像这样的行中的“d”指什么
function(d) { return d.source.x; }
它似乎是在声明一个函数并同时调用它。我知道它不一定是特定的字符“d”(例如,将“d”切换为“a”似乎没有什么区别,只要它在声明中和函数内完成即可。 )但是它指的是什么?输入到正在修改的对象中的数据?例如,如果我想打印出来(在属性之外)我该怎么做?
抱歉,我是 D3 的新手(而且总体来说对 JavaScript 相当陌生),所以我感觉答案是显而易见的,但我一直在查找它并通过教程,但我仍然迷失方向。提前致谢。
最佳答案
首先,您的代码存在一个简单的问题,导致所有节点都停留在左上角。您尝试使用以下代码定位每个节点:
node.attr("x", function(a) { return a.x; })
.attr("y", function(a) { return a.y; });
但是,节点
是g
的选择,它不采用x
和y
属性。。相反,您可以使用平移变换来移动每个节点
,例如
node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
进行此更改应该允许节点四处移动。
接下来,转向关于“d”的问题,我认为您需要了解的第一件事是您可以使用 D3 中的一系列元素来做什么。来自 the docs :选择(例如节点
)“是从当前文档中提取的元素数组”。选择元素后,您可以应用运算符来更改元素的属性或样式。您还可以将数据绑定(bind)到每个元素。
在您的情况下,您将数据绑定(bind)到选择的g
(节点):
var node = svg.selectAll(".node")
.data(nodes)
.enter().append("g")
您现在正在使用 attr
改变每个节点的位置。但是,您不是将每个元素的 x
和 y
属性设置为相同的值,而是传递 attr
anonymous function这将为每个节点返回一个(可能不同的)位置:
node.attr("x", function(a) { return a.x; })
.attr("y", function(a) { return a.y; });
attr 的文档中也解释了此行为:
Attribute values and such are specified as either constants or functions; the latter are evaluated for each element.
因此,d
表示节点
中的单个元素(对象)。
所以回到你的代码,在每个刻度上都会发生两件事:
- 每个节点(数据)的位置正在通过
force
重新计算。 - 然后,您传递给
force.on
的匿名函数会将每个相应元素移动到新位置。
关于javascript - d3.js 强制定向问题, "d"的意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20295700/