D3强制布局,即时创建链接数组

时间:2016-11-04 08:08:56

标签: javascript d3.js

我正在尝试启动并运行一个强制布局,并且我正在使用从API中提取的一些JSON,然后我需要将其操作到正确的格式D3中。

D3强制布局需要2个数组nodeslinks。从API返回时,JSON看起来像这样,

    [
  {
    "workbase" : "The House",
    "service_user" : "Joe Blogs",
    "service_user_id" : 100,
    "role" : "Coordinator",
    "staff_name" : "Jim Bean",
    "staff_id" : 1
  },
  {
    "workbase" : "The House",
    "service_user" : "Joe Blogs",
    "service_user_id" : 100,
    "role" : "Documentation",
    "staff_name" : "Jack Daniels",
    "staff_id" : 2
  },
  {
    "workbase" : "The House",
    "service_user" : "Joe Blogs",
    "service_user_id" : 100,
    "role" : "Activities",
    "staff_name" : "Morgan Spice",
    "staff_id" : 3
  },
  {
    "workbase" : "The House",
    "service_user" : "Joe Blogs",
    "service_user_id" : 100,
    "role" : "Wellbeing",
    "staff_name" : "Jonny Walker",
    "staff_id" : 4
  }
]

然后,我需要将此数据拆分为用户类型,susw,如下所示,并重命名一些属性并添加一些其他属性。

var sw  = [],
    su = [],
    links = [],
    edges = [];
    d3.json("test_example.json", function(error, json) {
        console.log(json);
        json.forEach(function(data) {
            console.log(data);
            sw.push({ 
                name : data.staff_name,
                id : data.staff_id,
                role : data.role,
                linked_to : data.service_user_id
            });
            if(_.findWhere(su, {name: data.service_user}) == undefined) {
                su.push({ name : data.service_user, id: data.service_user_id });
            }
        });
        var nodes = su.concat(sw);
        nodes.forEach(function(data){
            links.push({
                target: _.findIndex(nodes, function(user) { 
                    return user.id == data.linked_to; 
                }),
                source: data.id
            });
        });
    });

在此之后,我有2个看起来像这样的数组,

节点

enter image description here

链接

enter image description here

对于我的生活,我无法解决:

  
      
  • 1:为什么有5个链接应该和
  •   
  • 2:为什么第一个链接未定义。
  •   

有人有任何想法吗?

理想情况下,我应该能够遍历我的节点数组,并根据节点ID和链接ID创建tragets和source的链接数组。

1 个答案:

答案 0 :(得分:1)

  

1:为什么有5个链接应该有4个?

forEach每个数组元素执行一次提供的函数。因此,如果nodes有5个元素(您可以在链接的图像中轻松看到),并且此函数将对nodes数组中的每个元素执行一次,它将运行5次。 / p>

  

2:为什么第一个链接未定义?

linked_to数组的第一个对象中没有nodes个键。因此,您可以避免undefined只检查该密钥是否存在:

nodes.forEach(function(data){
    if(data.linked_to){
        links.push({
            target: nodes.findIndex(function(user) { 
                return user.id == data.linked_to; 
            }),
            source: data.id
        });
    }
});

此处,if(data.linked_to)会检查该密钥。

这是一个演示:



var json = [{
    "workbase": "The House",
    "service_user": "Joe Blogs",
    "service_user_id": 100,
    "role": "Coordinator",
    "staff_name": "Jim Bean",
    "staff_id": 1
}, {
    "workbase": "The House",
    "service_user": "Joe Blogs",
    "service_user_id": 100,
    "role": "Documentation",
    "staff_name": "Jack Daniels",
    "staff_id": 2
}, {
    "workbase": "The House",
    "service_user": "Joe Blogs",
    "service_user_id": 100,
    "role": "Activities",
    "staff_name": "Morgan Spice",
    "staff_id": 3
}, {
    "workbase": "The House",
    "service_user": "Joe Blogs",
    "service_user_id": 100,
    "role": "Wellbeing",
    "staff_name": "Jonny Walker",
    "staff_id": 4
}];

var sw = [],
    su = [],
    links = [],
    edges = [];
json.forEach(function(data) {
    sw.push({
        name: data.staff_name,
        id: data.staff_id,
        role: data.role,
        linked_to: data.service_user_id
    });
    if (_.findWhere(su, {
            name: data.service_user
        }) == undefined) {
        su.push({
            name: data.service_user,
            id: data.service_user_id
        });
    }
});
var nodes = su.concat(sw);
nodes.forEach(function(data) {
    if (data.linked_to) {
        links.push({
            target: nodes.findIndex(function(user) {
                return user.id == data.linked_to;
            }),
            source: data.id
        });
    }
});

console.log(links)

<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
&#13;
&#13;
&#13;

PS 您不需要forEach中的不良内容.js。您可以使用Array.prototype.findIndex