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

jas*_*epg 4 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}]...
Run Code Online (Sandbox Code Playgroud)

下面的代码用于提取该信息.它在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};
    }
Run Code Online (Sandbox Code Playgroud)

任何帮助,将不胜感激.

谢谢!

Chr*_*che 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);
Run Code Online (Sandbox Code Playgroud)

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

加载数据

为了加载数据,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
}
Run Code Online (Sandbox Code Playgroud)

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

格式化数据

从我在这里看到你的数据似乎只是一个链接列表,我只会考虑你的节点只是从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};});
Run Code Online (Sandbox Code Playgroud)

构建力导向图

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

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

现在,强制布局模拟已打开,它知道有数据,但仍然没有任何内容添加到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);
Run Code Online (Sandbox Code Playgroud)

有关类属性,请参阅示例.

声明tick()函数

最后,您必须声明将在force布局函数的每次迭代时调用的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; });
});
Run Code Online (Sandbox Code Playgroud)

结论

我刚刚翻译了您的数据的基本示例,以显示它的工作原理:http://bl.ocks.org/ChrisJamesC/5028030


要么...

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


要么...

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