d3.js强制导向的问题,“d”的意义?

时间:2013-11-30 02:07:05

标签: javascript d3.js force-layout

我在使用D3.js工作时遇到了一些麻烦。也就是说,我正在尝试使用http://bl.ocks.org/mbostock/1021953中的基本代码创建节点树。

enter image description here

我将其切换为内联加载数据,而不是从文件加载,因为我在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来说还是新手),所以我觉得答案很明显,但我一直在查找并通过教程,我仍然迷失方向。提前谢谢。

1 个答案:

答案 0 :(得分:2)

首先,您的代码存在一个简单问题,导致所有节点都停留在左上角。您正尝试使用代码定位每个节点:

node.attr("x", function(a) { return a.x; })
    .attr("y", function(a) { return a.y; }); 

但是,nodeg s 的选择,不会采用xy属性。相反,您可以使用translate transform移动每个node,例如

node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

进行此更改应允许节点四处移动。


接下来,转到关于“d”的问题,我认为您需要了解的第一件事是您可以使用D3中的一系列元素来完成。来自the docs:选择(例如nodes)“是从当前文档中提取的元素数组。”一旦选择了元素,就可以应用运算符来更改元素的属性或样式。您还可以将数据绑定到每个元素。

在您的情况下,您将数据绑定到选择的g s(节点):

var node = svg.selectAll(".node")
  .data(nodes)
  .enter().append("g")

然后您使用attr更改每个节点的位置。但是,您不是将每个元素的xy属性设置为相同的值,而是传递attranonymous function,它将返回(可能是不同的)位置每个节点:

node.attr("x", function(a) { return a.x; })
    .attr("y", function(a) { return a.y; }); 

attr的文档中也解释了这种行为:

  

属性值等指定为常量或   功能;后者将针对每个元素进行评估。

因此,d表示nodes中的单个元素(对象)。

所以回到你的代码,每一个滴答都会发生两件事情:

  1. 每个节点(数据)的位置由force重新计算。
  2. 然后,您传递给force.on的匿名函数将每个对应的元素移动到新位置。