强制定向图错误,“无法读取未定义的属性'推'”

Der*_*ith 5 javascript d3.js force-layout

我是编码的新手,最近开始使用d3生成力向图。使用链接导出节点时,我成功生成了一个四节点图。但是,当我显式列出节点时,我收到错误“未捕获的TypeError:无法读取未定义的属性'push'(d3.v3.min.js)”。我已经研究了对以下两个类似问题的回答,但是无法使用答案解决此问题。我试图删除尽可能多的不相关功能,谢谢。

JavaScript错误“未捕获的TypeError:无法调用未定义的方法'push'” D3.js

Uncaught TypeError:无法调用未定义的方法“ push”(d3强制布局)

强制定向图失败:

<script type="text/javascript" src="d3.v3.min.js"> </script>

<script>

var width = 900,
    height = 590;

var svg = d3.select("body")
        .append("svg")
        .attr("width", width)
        .attr("height", height)

var links = [
    {source: 'H', target: 'I'},
    {source: 'H', target: 'J'},
    {source: 'I', target: 'J'},
    {source: 'J', target: 'K'},
];

var nodes = [ 
    {name: 'H'},
    {name: 'I'},
    {name: 'J'},
    {name: 'K'},
];

var force = d3.layout.force()
    .size([width, height])
    .nodes(d3.values(nodes))
    .links(links)
    .on('tick', tick)
    .linkDistance(100)
    .gravity(.15)
    .friction(.8)
    .linkStrength(1)
    .charge(-425)
    .chargeDistance(600)
    .start();

var link = svg.selectAll('.link')
    .data(links)
    .enter().append('line')
    .attr('class', 'link');

var node = svg.selectAll('.node')
    .data(force.nodes())
    .enter().append('circle')
    .attr('class', 'node')
    .attr('r', width * 0.01)

function tick(e) {

    node.attr('cx', function(d) { return d.x; })
        .attr('cy', function(d) { return d.y; })
        .call(force.drag);

    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; });

};

    </script>
Run Code Online (Sandbox Code Playgroud)

强制有向图工作:

<script type="text/javascript" src="d3.v3.min.js"> </script>

<script>

var width = 900,
    height = 590;

var svg = d3.select("body")
        .append("svg")
        .attr("width", width)
        .attr("height", height)

var links = [
    {source: 'H', target: 'I'},
    {source: 'H', target: 'J'},
    {source: 'I', target: 'J'},
    {source: 'J', target: 'K'},
];

var nodes = {};
links.forEach(function(link) {
    link.source = nodes[link.source] ||
        (nodes[link.source] = {name: link.source});
    link.target = nodes[link.target] ||
        (nodes[link.target] = {name: link.target});
        });

var force = d3.layout.force()
    .size([width, height])
    .nodes(d3.values(nodes))
    .links(links)
    .on('tick', tick)
    .linkDistance(100)
    .gravity(.15)
    .friction(.8)
    .linkStrength(1)
    .charge(-425)
    .chargeDistance(600)
    .start();

var link = svg.selectAll('.link')
    .data(links)
    .enter().append('line')
    .attr('class', 'link');

var node = svg.selectAll('.node')
    .data(force.nodes())
    .enter().append('circle')
    .attr('class', 'node')
    .attr('r', width * 0.01)

function tick(e) {

    node.attr('cx', function(d) { return d.x; })
        .attr('cy', function(d) { return d.y; })
        .call(force.drag);

    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; });

};

    </script>
Run Code Online (Sandbox Code Playgroud)

alt*_*lus 7

API 文档有它:

注意:源和目标属性的值最初可能被指定为节点数组的索引;这些将在调用 start 后被引用替换。

links 数组需要通过索引或通过引用节点的对象来引用节点。在您的工作示例中,这是在从链接创建节点时完成的:

link.source =                                   // (3)
    nodes[link.source] ||                       // (1)
    (nodes[link.source] = {name: link.source}); // (2)
Run Code Online (Sandbox Code Playgroud)

这将 (1) 使用节点的文字名称 from link.source,例如H,并从nodes数组中获取节点对象(如果它已经存在)。如果在nodes数组中找不到它,||则评估运算符的右侧,这将 (2) 创建一个新的节点对象并将其放入数组中。在任何一种情况下,整个表达式 (1) ||(2) 都将计算为节点对象的引用,然后 (3) 分配给link.source。因此,您不仅要从链接创建节点,还要更改链接本身。初始化后,您的链接数组将如下所示:

[
  {source: { name: 'H' }, target: { name: 'I' }},
  {source: { name: 'H' }, target: { name: 'J' }},
  {source: { name: 'I' }, target: { name: 'J' }},
  {source: { name: 'J' }, target: { name: 'K' }},
];
Run Code Online (Sandbox Code Playgroud)

您现在已准备好包含所有链接对象sourcetarget包含节点对象引用的属性的链接数组。


如果您已经准备好节点的对象,您可以通过将引用放入自己来初始化链接数组,或者您可以通过索引引用节点将其留给 D3:

var links = [
    {source: 0, target: 1},
    {source: 0, target: 2},
    {source: 1, target: 2},
    {source: 2, target: 3},
];

var nodes = [ 
    {name: 'H'},
    {name: 'I'},
    {name: 'J'},
    {name: 'K'},
];
Run Code Online (Sandbox Code Playgroud)

将它放在您的非工作示例中将使其按预期工作:

link.source =                                   // (3)
    nodes[link.source] ||                       // (1)
    (nodes[link.source] = {name: link.source}); // (2)
Run Code Online (Sandbox Code Playgroud)
[
  {source: { name: 'H' }, target: { name: 'I' }},
  {source: { name: 'H' }, target: { name: 'J' }},
  {source: { name: 'I' }, target: { name: 'J' }},
  {source: { name: 'J' }, target: { name: 'K' }},
];
Run Code Online (Sandbox Code Playgroud)