D3.js 网络图使用力导向布局和矩形节点

Posted

技术标签:

【中文标题】D3.js 网络图使用力导向布局和矩形节点【英文标题】:D3.js network graph using force-directed layout and rectangles for nodes 【发布时间】:2015-08-12 14:46:52 【问题描述】:

我正在尝试修改 Mike 的 Force-Directed Graph 示例以使用矩形而不是圆形作为节点。另外,我想要矩形内的文本。

我有正确显示文本的矩形,但是它们没有附加到链接上,并且它们不会移动。

这是一个 codepen 链接:http://codepen.io/anon/pen/gpgWaz

var width = 960,
    height = 500;

var color = d3.scale.category20();

var force = d3.layout.force()
    .charge(-120)
    .linkDistance(30)
    .size([width, height]);

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

force
    .nodes(graph.nodes)
    .links(graph.links)
    .start();

var link = svg.selectAll(".link")
    .data(graph.links)
    .enter().append("line")
    .attr("class", "link")
    .style("stroke-width", function(d) 
        return Math.sqrt(d.value);
    );

var node = svg.selectAll(".node")
    .data(graph.nodes)
    .enter()
    .append("g")
    .attr("transform", function(d) 
        return "translate(" + d.x + "," + d.y + ")";
    )
    .call(force.drag);

node.append("rect")
    .attr("class", "node")
    .attr("width", 100)
    .attr("height", 35)
    .style("fill", function(d) 
        return color(d.group);
    )
    .style("stroke", "black")
    .style("stroke-width", "1px");

node.append("text")
    .text(function(d) 
        return d.name;
    )
    .style("font-size", "12px")
    .attr("dy", "1em");

node.append("title")
    .text(function(d) 
        return d.name;
    );

force.on("tick", function() 
    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;
        );

    node.attr("x", function(d) 
            return d.x;
        )
        .attr("y", function(d) 
            return d.y;
        );
);

更新

感谢Lars 的评论,以及他的codepen 现在可以使用了。

我对代码所做的更新:

    添加由 Lars 说明的变换 将链接更改为在矩形中心连接 为矩形添加圆角 给文本一个小边距缩进 改为使用窗口宽度/高度

这是我的新代码笔:http://codepen.io/anon/pen/bdgREd

var width = window.innerWidth,
    height = window.innerHeight,
    nodeWidth = 100,
    nodeHeight = 35;

var color = d3.scale.category20();

var force = d3.layout.force()
    .charge(-1500)
    .linkDistance(100)
    .friction(0.5)
    .size([width, height]);

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

force
    .nodes(graph.nodes)
    .links(graph.links)
    .start();

var link = svg.selectAll(".link")
    .data(graph.links)
    .enter().append("line")
    .attr("class", "link")
    .style("stroke-width", function(d) 
        return Math.sqrt(d.value);
    );

var node = svg.selectAll(".node")
    .data(graph.nodes)
    .enter()
    .append("g")
    .attr("transform", function(d) 
        return "translate(" + d.x + "," + d.y + ")";
    )
    .call(force.drag);

node.append("rect")
    .attr("class", "node")
    .attr("width", nodeWidth)
    .attr("height", nodeHeight)
    .attr("rx", 5)
    .attr("ry", 5)
    .style("fill", function(d) 
        return color(d.group);
    )
    .style("stroke", "black")
    .style("stroke-width", "1px");

node.append("text")
    .attr("x", 5)
    .attr("y", 2)
    .text(function(d) 
        return d.name;
    )
    .style("font-size", "12px")
    .attr("dy", "1em");

node.append("title")
    .text(function(d) 
        return d.name;
    );

force.on("tick", function() 
    link.attr("x1", function(d) 
            return d.source.x + (nodeWidth / 2);
        )
        .attr("y1", function(d) 
            return d.source.y + (nodeHeight / 2);
        )
        .attr("x2", function(d) 
            return d.target.x + (nodeWidth / 2);
        )
        .attr("y2", function(d) 
            return d.target.y + (nodeHeight / 2);
        );

    node.attr("transform", function(d) 
            return "translate(" + d.x + "," + d.y + ")";
        );
);

【问题讨论】:

您需要像附加矩形时那样设置transform 属性:codepen.io/anon/pen/YXNVNY 做到了。如果您将此作为答案发布,我会接受。谢谢! 【参考方案1】:

您正在设置g 元素上的xy 属性来改变它们的位置——这不会做任何事情。您需要设置 transform 属性,就像您在添加 g 元素时所做的那样。所以你的 tick 处理函数将包含

node.attr("transform", function(d) 
    return "translate(" + d.x + "," + d.y + ")";
);

而不是

node.attr("x", function(d) 
        return d.x;
    )
    .attr("y", function(d) 
        return d.y;
    );

完整的演示here。

【讨论】:

以上是关于D3.js 网络图使用力导向布局和矩形节点的主要内容,如果未能解决你的问题,请参考以下文章

D3.js 力导向图的拖拽(drag)与缩放(zoom)

力导向图布局的性能和复杂性?

ECharts 力导向布局图怎么将数据库里的数据赋值给各个节点

D3.js中Force-Directed Graph详解

D3.js中Force-Directed Graph详解

SVG力导向图,当鼠标经过某一节点时(mouseover),显示两层与其相关联的节点和连线,该如何实现?