无法在d3.force实现中读取未定义的属性“权重”

时间:2013-02-24 05:07:07

标签: javascript d3.js force-layout

我一直坚持这个问题一段时间,甚至根据现有的答案也不知道该做什么。我一直在统一响应的最后一个JSON条目上得到此错误。

...{"paperCount": 1, "PMIDs": [20626970], "authorA": 79, "authorB": 80}, 
{"paperCount": 1, "PMIDs": [20492581], "authorA": 81, "authorB": 82}, 
{"paperCount": 1, "PMIDs": [20492581], "authorA": 81, "authorB": 83}, 
{"paperCount": 1, "PMIDs": [20492581], "authorA": 81, "authorB": 84}, 
{"paperCount": 1, "PMIDs": [20492581], "authorA": 82, "authorB": 83}, 
{"paperCount": 1, "PMIDs": [20492581], "authorA": 82, "authorB": 84}, 
{"paperCount": 1, "PMIDs": [20492581], "authorA": 83, "authorB": 84}]...

下面的代码用于提取该信息。它在for循环中一直失败......

  $.getJSON('/papers.txt', function(response){
    var w = 1280,
    h = 900,
    fill = d3.scale.category10(),
    nodes = d3.range(1000).map(Object),
    links = d3.range(1000).map(Object);

    var index = 0;
    var mouseX = 0,
      mouseY = 0;

    for (var j = 0; j < response.length; j++){
      links[j] = {source: nodes[response[j].authorA], target: nodes[response[j].authorB], value: response[j].paperCount};
    }

任何帮助都将不胜感激。

谢谢!

1 个答案:

答案 0 :(得分:17)

简介

最重要的是,我建议你仔细看看documentation,因为我在这个答案中所写的内容都写在其中

好吧,首先在你提供的代码中你根本不使用force布局,你没有用它声明节点,你没有在svg中包含节点...所以基本上,从什么我明白了,毫无疑问它会引发错误。您应该查看this example以了解如何创建最小力导向图。

我还建议下次有问题的时候,你建立一个jsFiddle,这样我们就可以对它进行处理,看看问题出在哪里,因为你提供的代码不可能确切地看到它出错的地方因为你不以传统方式使用d3.js。

所以,让我们回到基础。

定义图表

首先,在加载数据之前,我们需要定义图的一般属性:

var width = 960,
    height = 500;

var color = d3.scale.category20();

/* Here we define that we will use the force layout an we add some parameters to setup the basic layout of the graph */
var force = d3.layout.force() 
    .charge(-120)
    .linkDistance(30)
    .size([width, height]);

/* Here we include the graph in the page */
var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

但是,目前图表没有节点。我们需要加载数据。

加载数据

要加载数据,d3提供了一个帮助器,所以让我们使用它而不是jQuery的一个,不需要混合另一个库。有关信息,json加载程序需要.json文件,因此即使它们包含json格式化数据,也不要使用.txt文件。

d3.json("papers.json", function(error, data) {
    // do whatever you need to do with the json data, for this example : create the graph
}

我以后要做的所有事情都应该包含在这些大括号内。

格式化数据

从我在这里看到的你的数据似乎只是一个链接列表,我只会考虑你的节点只是从0到99的点。

var my_nodes = d3.range(100).map(function(d){return {"name": d};});
var my_links = my_data.map(function(d){return {"source": d.authorA, "target": d.authorB, "value":d.paperCount, "origin": d};});

构建力导向图

从我的数据中构建力导向图,

force // I use the previously defined variable force to add the data.
    .nodes(my_nodes)
    .links(my_links)
    .start() //start the simulation

现在,强制布局模拟已启动,它知道有数据,但仍然没有任何内容添加到svg。我们现在将添加所有内容:

var link = svg.selectAll(".link")
    .data(my_links)
    .enter().append("line")
    .attr("class", "link")

var node = svg.selectAll(".node")
    .data(my_nodes)
    .enter().append("circle") // If you wonder why enter() is used, see the documentation
    .attr("class", "node")
    .attr("r", 5)
    .style("fill", function(d) { return "red"; })
    .call(force.drag);

有关课程属性,请参阅example

声明tick()函数

最后,你必须声明将在力布局函数的每次迭代中调用的tick函数

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("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; });
});

结论

我刚刚为您的数据翻译了基本示例,以证明其有效:http://bl.ocks.org/ChrisJamesC/5028030


或者...

也许,你遇到的主要问题是你不明白$ .getJson()函数是异步所以你不应该只在其中构建links向量,你也应该只在这个函数中使用它,否则它将不会被加载。


或者...

也许,您的错误只是因为您应该将json文件命名为/papers.json而不是/papers.txt