【问题标题】:D3 force layout - linking nodes by name instead of indexD3 强制布局 - 按名称而不是索引链接节点
【发布时间】:2014-07-22 02:16:24
【问题描述】:

我正在尝试通过 ID 而不是索引链接 d3 节点(节点 ID 由我的应用程序生成)。

这是我的节点:

"Nodes": [
    {
      "Id": "338",
      "Name": "TEST NODE ONE",
      "Url": "http://www.google.com"
    },
    {
      "Id": "340",
      "Name": "TEST NODE TWO",
      "Url": "http://www.yahoo.com"
    },
    {
      "Id": "341",
      "Name": "TEST NODE THREE",
      "Url": "http://www.stackoverflow.com"
    },
    {
      "Id": "342",
      "Name": "TEST NODE FOUR",
      "Url": "http://www.reddit.com"
    }
  ]

它们目前通过索引链接:

  "links": [
    {
      "source": 0,
      "target": 0,
      "value": "0"
    },
    {
      "source": 0,
      "target": 1,
      "value": "0"
    },
    {
      "source": 1,
      "target": 2,
      "value": "0"
    },
    {
      "source": 3,
      "target": 2,
      "value": "0"
    }
  ]

但是,我想通过“Id”链接它们:

  "Links": [
    {
      "Source": "338",
      "Target": "338",
      "Value": "0"
    },
    {
      "Source": "338",
      "Target": "340",
      "Value": "0"
    },
    {
      "Source": "340",
      "Target": "341",
      "Value": "0"
    },
    {
      "Source": "342",
      "Target": "341",
      "Value": "0"
    }
  ]

我已经尝试过这里提出的解决方案:https://groups.google.com/forum/#!msg/d3-js/LWuhBeEipz4/0kZIojCYvhIJ

在调用 force.nodes 之前添加以下行:

  // make links reference nodes directly for this particular data format:
  var hash_lookup = [];
  // make it so we can lookup nodes in O(1):
  json.Nodes.forEach(function(d, i) {
    hash_lookup[d.Id] = d;
  });
  json.Links.forEach(function(d, i) {
    d.source = hash_lookup[d.Source];
    d.target = hash_lookup[d.Target];
  });

我已尝试调试上述内容,但无法弄清楚。我收到以下错误消息(这通常意味着我没有正确设置链接):

Uncaught TypeError: Cannot read property 'weight' of undefined

链接到我的完整 JS:http://jsfiddle.net/9sMrw/

【问题讨论】:

    标签: javascript json d3.js


    【解决方案1】:

    这是一个简单的方法:

    var edges = [];
    json.Links.forEach(function(e) {
        var sourceNode = json.Nodes.filter(function(n) {
            return n.Id === e.Source;
        })[0],
            targetNode = json.Nodes.filter(function(n) {
                return n.Id === e.Target;
            })[0];
    
        edges.push({
            source: sourceNode,
            target: targetNode,
            value: e.Value
        });
    });
    
    force
        .nodes(json.Nodes)
        .links(edges)
        .start();
    
    var link = svg.selectAll(".link")
        .data(edges)
        ...
    

    这是一个有效的PLUNK。 (为了安全起见,你应该分叉它,以防我无意中删除它。)

    【讨论】:

    • sourceNodetargetNode 可以引用原始节点数组中的对象的原因是什么?是因为 DOM 元素最终会引用原始节点数组中的那些完全相同的对象吗? (通过force.nodes(json.Nodes).....start()
    • 在这里,索引被转换为节点:github.com/mbostock/d3/blob/master/src/layout/… 所以,这里的代码跳过了这一步,因为输出是链接对象最终的样子。
    • 非常棒!谢谢!
    • 我已将您的更改应用到我的代码中,但错误“无法读取未定义的属性'权重'”仍然存在...我不知道...请参阅:plnkr.co/edit/OhRrufGi7yF42umrhdBX?p=preview
    • 请看这些SO answers
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-23
    • 2014-11-20
    • 1970-01-01
    相关资源
    最近更新 更多