强制定向图形错误,“无法读取未定义的属性'推'"; [英] Force Directed Graph Error, "Cannot Read Property 'Push' of Undefined"

查看:51
本文介绍了强制定向图形错误,“无法读取未定义的属性'推'";的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am new to coding and recently began using d3 to generate a force directed graph. I successfully generated a four node graph when using the links to derive the nodes. However, when I explicitly list the nodes I receive the error "Uncaught TypeError: Cannot read property 'push' of undefined (d3.v3.min.js)". I have studied responses to the following two similar questions but have been unable to resolve this issue using the answers. I attempted to remove as many of the non-relevant features as possible, thanks.

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

Uncaught TypeError:无法调用方法'推送"(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>

强制有向图有效:

<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>

推荐答案

API文档具有它:

注意:最初可以将源和目标属性的值指定为 nodes 数组的索引;调用开始后,这些将被引用替换.

Note: the values of the source and target attributes may be initially specified as indexes into the nodes array; these will be replaced by references after the call to start.

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

The links array needs to be referring to the nodes either by index or by reference to the nodes' objects. In your working example this is done when creating the nodes from the links:

link.source =                                   // (3)
    nodes[link.source] ||                       // (1)
    (nodes[link.source] = {name: link.source}); // (2)

这将(1)使用link.source中节点的文字名称,例如H,并从nodes数组中获取节点对象(如果已存在).如果在nodes数组中未找到它,则对||运算符的右侧进行求值,这将(2)创建一个新的节点对象并将其放置在数组中.在任何一种情况下,整个表达式(1)||(2)将求值到节点对象的引用,该对象然后被(3)分配给link.source.因此,您不仅在根据链接创建节点,而且还要更改链接本身.初始化之后,您的links数组将如下所示:

This will (1) use the literal name of the node from link.source, say H, and fetch the node object from the nodes array if it is already there. If it is not found in the nodes array, the right hand side of the || operator is evaluated which will (2) create a new node object and place it in the array. In either case the whole expression (1) || (2) will evaluate to the reference of a node object which is then (3) assigned to link.source. Hence, you are not just creating nodes from links but also altering the links themselves. After that initialization your links array will be like this:

[
  {source: { name: 'H' }, target: { name: 'I' }},
  {source: { name: 'H' }, target: { name: 'J' }},
  {source: { name: 'I' }, target: { name: 'J' }},
  {source: { name: 'J' }, target: { name: 'K' }},
];

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

You now have the links array ready with all link objects' source and target properties containing references to node objects.

如果您已经准备好节点的对象,则可以通过放置引用来自己对links数组进行初始化,也可以通过按索引引用节点将其留给D3:

If you already have the nodes' objects ready, you may do the initialization of the links array yourself by putting the references in or you may leave this to D3 by referring to the nodes by index:

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'},
];

将其放在您无法使用的示例中将使其按预期工作:

Putting this in your non-working example will make it work as expected:

var width = 600,
    height = 400;

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

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'},
];

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 src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

这篇关于强制定向图形错误,“无法读取未定义的属性'推'";的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆