d3.js:链接相关项目

d3.js:链接相关项目,d3.js,relationship,D3.js,Relationship,我正在尝试使用d3.js创建一个图表,显示项目之间的关系或链接 其基本思想是: 当我将鼠标悬停或单击其中一个项目时,相关项目将高亮显示 我已经看过了d3.layout.tree,但它似乎与我正在尝试的有所不同 我看到这把小提琴: 这似乎是一个正确方向的开始 基于这把小提琴,我用自己的数据集构建了这把小提琴 一开始它看起来会起作用。但后来我意识到,我得到的是叠加在其他圆圈上的圆圈,以及多个副本。。。我明白为什么了 我构建数据的方式可能有问题。这是可以改变的 var data = {

我正在尝试使用d3.js创建一个图表,显示项目之间的关系或链接

其基本思想是:

当我将鼠标悬停或单击其中一个项目时,相关项目将高亮显示

我已经看过了d3.layout.tree,但它似乎与我正在尝试的有所不同

我看到这把小提琴: 这似乎是一个正确方向的开始

基于这把小提琴,我用自己的数据集构建了这把小提琴 一开始它看起来会起作用。但后来我意识到,我得到的是叠加在其他圆圈上的圆圈,以及多个副本。。。我明白为什么了

我构建数据的方式可能有问题。这是可以改变的

    var data = {
    "Product": [
        {
            "type": "product",
            "name": "Product 1",
            "links": [
                {
                    "name": "Industry 1",
                    "type": "industry",
                    "percent": 0.12,
                    "count": 149
                },
                {
                    "name": "Industry 2",
                    "type": "industry",
                    "percent": 0.18,
                    "count": 180
                },
                {
                    "name": "Industry 3",
                    "type": "industry",
                    "percent": 0.17,
                    "count": 152
                },
                {
                    "name": "Industry 4",
                    "type": "industry",
                    "percent": 0.16,
                    "count": 175
                },
                {
                    "name": "Industry 5",
                    "type": "industry",
                    "percent": 0.25,
                    "count": 21
                },
                {
                    "name": "Size A",
                    "type": "size",
                    "percent": 0.24,
                    "count": 21
                },
                {
                    "name": "Size B",
                    "type": "size",
                    "percent": 0.15,
                    "count": 49
                },
                {
                    "name": "Size C",
                    "type": "size",
                    "percent": 0.15,
                    "count": 83
                },
                {
                    "name": "Size D",
                    "type": "size",
                    "percent": 0.17,
                    "count": 128
                },
                {
                    "name": "Size E",
                    "type": "size",
                    "percent": 0.13,
                    "count": 241
                },
                {
                    "name": "Size F",
                    "type": "size",
                    "percent": 0.08,
                    "count": 161
                }            ]
        },
        {
            "type": "product",
            "name": "Product 2",
            "links": [
                {
                    "name": "Industry 1",
                    "type": "industry",
                    "percent": 0.06,
                    "count": 15
                },
                {
                    "name": "Industry 3",
                    "type": "industry",
                    "percent": 0.21,
                    "count": 52
                },
                {
                    "name": "Industry 5",
                    "type": "industry",
                    "percent": 0.15,
                    "count": 39
                },
                {
                    "name": "Size C",
                    "type": "size",
                    "percent": 0.28,
                    "count": 78
                },
                {
                    "name": "Size D",
                    "type": "size",
                    "percent": 0.13,
                    "count": 73
                }
            ]
        },
        {
            "type": "product",
            "name": "Product 3",
            "links": [
                {
                    "name": "Industry 4",
                    "type": "industry",
                    "percent": 0.18,
                    "count": 15
                },
                {
                    "name": "Industry 5",
                    "type": "industry",
                    "percent": 0.19,
                    "count": 52
                },
                {
                    "name": "Size A",
                    "type": "size",
                    "percent": 0.15,
                    "count": 3
                },
                {
                    "name": "Size D",
                    "type": "size",
                    "percent": 0.18,
                    "count": 55
                },
                {
                    "name": "Size E",
                    "type": "size",
                    "percent": 0.14,
                    "count": 47
                },
                {
                    "name": "Size F",
                    "type": "size",
                    "percent": 0.13,
                    "count": 24
                }
            ]
        },
        {
            "type": "product",
            "name": "Product 4",
            "links": [
                {
                    "name": "Industry 2",
                    "type": "industry",
                    "percent": 0.1,
                    "count": null
                },
                {
                    "name": "Industry 3",
                    "type": "industry",
                    "percent": 0.01,
                    "count": null
                },
                {
                    "name": "Size A",
                    "type": "size",
                    "percent": 0.21,
                    "count": null
                },
                {
                    "name": "Size B",
                    "type": "size",
                    "percent": 0.11,
                    "count": null
                },
                {
                    "name": "Size C",
                    "type": "size",
                    "percent": 0.18,
                    "count": null
                },
                {
                    "name": "Size D",
                    "type": "size",
                    "percent": 0.14,
                    "count": null
                }            
            ]
        },
        {
            "type": "product",
            "name": "Product 5",
            "links": [
                {
                    "name": "Industry 1",
                    "type": "industry",
                    "percent": 0.1,
                    "count": null
                },
                {
                    "name": "Industry 2",
                    "type": "industry",
                    "percent": 0.15,
                    "count": null
                },
                {
                    "name": "Industry 3",
                    "type": "industry",
                    "percent": 0.03,
                    "count": null
                },
                {
                    "name": "Industry 4",
                    "type": "industry",
                    "percent": 0.08,
                    "count": null
                },
                {
                    "name": "Size 2",
                    "type": "size",
                    "percent": 0.08,
                    "count": null
                },
                {
                    "name": "Size 3",
                    "type": "size",
                    "percent": 0.18,
                    "count": null
                },
                {
                    "name": "Size 5",
                    "type": "size",
                    "percent": 0.25,
                    "count": null
                }
            ]
        }
    ],
    "Industry": [
        {
            "type": "industry",
            "name": "Agriculture, Forestry & Fishery"
        },
        {
            "type": "industry",
            "name": "Arts & Entertainment"
        },
        {
            "type": "industry",
            "name": "Construction"
        },
        {
            "type": "industry",
            "name": "Educational Services"
        },
        {
            "type": "industry",
            "name": "Finance & Insurance"
        },
        {
            "type": "industry",
            "name": "Health Care & Social Assistance"
        },
        {
            "type": "industry",
            "name": "Manufacturing"
        },
        {
            "type": "industry",
            "name": "Mining"
        },
        {
            "type": "industry",
            "name": "Professional Services"
        },
        {
            "type": "industry",
            "name": "Public Administration"
        },
        {
            "type": "industry",
            "name": "Real Estate"
        },
        {
            "type": "industry",
            "name": "Retail Trade"
        },
        {
            "type": "industry",
            "name": "Services - Other"
        },
        {
            "type": "industry",
            "name": "Technology & Communication"
        },
        {
            "type": "industry",
            "name": "Transportation & Warehousing"
        },
        {
            "type": "industry",
            "name": "Utilities"
        },
        {
            "type": "industry",
            "name": "Wholesale Trade"
        }
    ],
    "Size": [
        {
            "type": "size",
            "name": "Size A"
        },
        {
            "type": "size",
            "name": "Size B"
        },
        {
            "type": "size",
            "name": "Size C"
        },
        {
            "type": "size",
            "name": "Size D"
        },
        {
            "type": "size",
            "name": "Size E"
        },
        {
            "type": "size",
            "name": "Size F"
        },
        {
            "type": "size",
            "name": "Size G"
        },
        {
            "type": "size",
            "name": "Size H"
        }
    ]
};
我的想法是,我可以将每种产品类型下的“链接”与匹配的规模或行业类型相匹配

我的javascript在这里:

var width = 600,
    height = 600,
    margin = {top: 16, right: 16, bottom: 16, left: 16},
    radius = 10, 
    gap = 24;

var dProduct = data.Product;

// test layout
var nodes = [];
var links = [];
dProduct.forEach(function(d, i) {
    d.x = width/2;
    d.y = margin.top + gap*i;
    nodes.push(d);
    d.links.forEach(function(c, i) {
        if(c.type === 'industry'){
            c.x = margin.left;
            c.y = margin.top + gap * (i+1) -2*radius;
        }else if (c.type === 'size'){
            c.x = width-margin.right-radius*2;
            c.y = margin.top + gap * (i+1) -2*radius;
        }
        nodes.push(c);

        var a = {x:c.y, y:c.x};
        var b = {x:d.y, y:d.x};
        links.push({source: b, target: a});
    });
});

var color = d3.scale.category20();

var svg = d3.select("#chart").append("svg")
        .attr("width", width)
        .attr("height", height)
        .append("g");
var diagonal = d3.svg.diagonal()
        .projection(function(d) { return [d.y, d.x]; });

var link = svg.selectAll(".link")
        .data(links)
        .enter().append("path")
        .attr("class", "link")
        .attr("d", diagonal);

var circle = svg.selectAll(".circle")
        .data(nodes)
        .enter()
        .append("g")
        .attr("class", "circle");

var el = circle.append("circle")
        .attr("cx", function(d) {return d.x})
        .attr("cy", function(d) {return d.y})
        .attr("r", radius)
        .style("fill", function(d) {return color(d.name)})
        .append("title").text(function(d) {return d.name});
我认为主要的问题是,我基本上是从链接创建大小和行业节点,而不是创建完整的节点集然后链接它们

如何布局这三种类型(行业、产品、规模),然后创建产品与其他两种类型之间的链接?或者更准确地说,在布局3种类型之后,如何创建链接?


谢谢

如果我理解正确,而您的意思是您的问题是获得了节点的多个副本,那么通过确保节点只添加到
节点
数组一次,这应该很容易解决。确保唯一性的一种方法是使用关联数组,如
d3.map

var nodeMap = d3.map();
var links = [];
dProduct.forEach(function(d, i) {
    d.x = width/2;
    d.y = margin.top + gap*i;
    nodeMap.set(d.name, d);
    d.links.forEach(function(c, i) {
        if(c.type === 'industry'){
            c.x = margin.left;
            c.y = margin.top + gap * (i+1) -2*radius;
        }else if (c.type === 'size'){
            c.x = width-margin.right-radius*2;
            c.y = margin.top + gap * (i+1) -2*radius;
        }
        nodeMap.set(c.name, c);

        var a = {x:c.y, y:c.x};
        var b = {x:d.y, y:d.x};
        links.push({source: b, target: a});
    });
});

var nodes = nodeMap.values();
请注意,此代码的唯一更改是在循环中使用
nodeMap
而不是
nodes
,然后在末尾调用
nodeMap.values()


在此之后,
节点
应该是一个独特的节点数组,您可以使用它来创建圆圈,
链接
仍然应该包含与之前相同的所有信息,以链接所有内容。

谢谢Scott!在昨晚花了一些时间阅读之后,我认为答案可能涉及到.map(),但不确定如何。事实上,我昨晚修改了我的数据集,这样我就有了节点和链接,每个节点都有一个唯一的id,每个链接都有一个源键和目标键。但是,使用您的示例和旧数据,您的示例消除了重复节点,但它没有通往任何地方的路径:越来越近!找到解决办法了吗?如果你能分享,我会很高兴。抱歉@Fr0zenFyr,我没有解决这个问题。我可能会在几个月后回到它,并会再试一次。谢谢回复。我也在研究一些和你的问题差不多的东西。如果我在你面前找到解决方案,我会发布一个答案。