4

我已经被这个问题困扰了一段时间,即使基于现有的答案也不知道该怎么做。我在统一响应的最后一个 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};
    }

任何帮助,将不胜感激。

谢谢!

4

1 回答 1

17

介绍

首先,我建议您仔细阅读文档,因为我在这个答案中要说的都写在里面

好吧,首先在您提供的代码中,您根本不使用强制布局,您没有使用它声明节点,您没有在 svg 中包含节点......所以基本上,从我所看到的,毫无疑问,它会引发错误。你应该看看这个例子,看看如何创建一个最小力有向图。

我还建议下次您有问题时,您可以构建一个 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 提供了一个 helper,所以让我们使用它来代替 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);

有关类属性,请参见示例

声明 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.

于 2013-02-25T05:59:30.053 回答