当前位置: 首页 > 知识库问答 >
问题:

如何使用 D3 布局非树层次结构

阮炯
2023-03-14

D3 具有多种布局,用于严格树的有向图,如下所示:

A
|\
B C
 / \
D   E

我需要绘制一个不是树的节点层次结构,而是一个有向无环图。这是树布局的问题,因为几个分支收敛:

A
|\
B C
 \|
  D

有人知道一般层次结构的D3布局吗?或者,对现有的treelayout进行一些巧妙的破解?我注意到GraphVis很好地处理了这种情况,但D3生成的图更适合这里的需求。

共有3个答案

佟阳焱
2023-03-14

一般来说,对于树和数据层次结构,您只需要在B和C的子列表中都有“D”。

创建您的节点列表,确保您返回了一个唯一的id,以便“D”不会出现两次。

vis.selectAll("g.node").data(nodes, function(d) { return d.id; });

然后当您致电时

var links = tree.links(nodes)

您应该让D作为“目标”出现两次(B和C分别作为“源”),这导致两行指向单个节点“D”。

穆丁雨
2023-03-14

例如:“强制定向树”说明了一个经常有效的技巧。在示例中,力方向的行为在每个刻度上进行调整,以便节点根据链接的方向略微向上或向下漂移。如图所示,这将对树很好,但我发现它对于非循环图也可以很好地工作。没有promise,但可能会有所帮助。

辛盛
2023-03-14

您可以创建自己的代码,而不必依赖 D3 布局来完成它。

我在jsFiddle中提供了一个例子。该示例非常简单,需要稍微处理一下以适应更复杂的示例。

该示例也可以重新处理分层数据,只需相对较少的努力。

以下是我在jsFiddle中使用的代码:

 // Sample data set
var json = {
    nodes: [{
        name: 'A'},
    {
        name: 'B'},
    {
        name: 'C'},
    {
        name: 'D'}],
    links: [{
        source: 'A',
        target: 'B'},
    {
        source: 'A',
        target: 'C'},
    {
        source: 'B',
        target: 'D'},
    {
        source: 'C',
        target: 'D'}
                                                                                   ]

};

var vis = d3.select('#vis').attr('transform', 'translate(20, 20)');

// Build initial link elements - Build first so they are under the nodes
var links = vis.selectAll('line.link').data(json.links);
links.enter().append('line').attr('class', 'link').attr('stroke', '#000');

// Build initial node elements
var nodes = vis.selectAll('g.node').data(json.nodes);
nodes.enter().append('g').attr('class', 'node').append('circle').attr('r', 10).append('title').text(function(d) {
    return d.name;
});

// Store nodes in a hash by name
var nodesByName = {};
nodes.each(function(d) {
    nodesByName[d.name] = d;
});

// Convert link references to objects
links.each(function(link) {
    link.source = nodesByName[link.source];
    link.target = nodesByName[link.target];
    if (!link.source.links) {
        link.source.links = [];
    }
    link.source.links.push(link.target);
    if (!link.target.links) {
        link.target.links = [];
    }
    link.target.links.push(link.source);
});

// Compute positions based on distance from root
var setPosition = function(node, i, depth) {
    if (!depth) {
        depth = 0;
    }
    if (!node.x) {
        node.x = (i + 1) * 40;
        node.y = (depth + 1) * 40;
        if (depth <= 1) {
            node.links.each(function(d, i2) {
                setPosition(d, i2, depth + 1);
            });
        }

    }

};
nodes.each(setPosition);

// Update inserted elements with computed positions
nodes.attr('transform', function(d) {
    return 'translate(' + d.x + ', ' + d.y + ')';
});

links.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;
});
 类似资料:
  • 分层布局是一种抽象布局,不直接使用。但它允许在不同的分层布局中共享节点。请看下列例子: • Cluster -簇实体构成树状图。 • Pack -使用递归圆填充法创建一个分层布局。 • Partition -将节点树递归划分成辐射状或环状。 • Tree -将节点树整齐放置。 • Treemap -使用递归空间划分显示节点树。 虽然不是分层布局,但捆绑布局可以同分层共同使用。 d3.layout.

  • 问题内容: 我有一个表,它表示类别层次结构,层次结构顶部的元素的父ID为0。在CatID列中有超过54K个唯一ID。每个ID可以是另一个ID的父对象。类别深入8个级别。该表如下所示: 这就是我想要实现的结果: 我怎样才能做到这一点?我是否需要某种循环才能遍历所有ID? 有人可以帮忙吗? 问题答案: 这里是:

  • 问题内容: 像这样对表格进行排序的最佳方法是什么: 要通过分级排序,它 的ID 或 名字 : “比萨饼” //节点1 “piperoni” //节点1.1 “奶酪” //节点1.2 “额外的奶酪” //节点1.2.1 “vegetariana” //节点1.3 “汉堡” //节点2 ‘咖啡’//节点3 编辑: 名称 末尾的数字是为了更好地可视化strucutre,而不是用于排序。 编辑2: 正如多

  • 树布局能够用莱因戈尔德-蒂尔福德算法产生一个整洁的树状结点-链接图。例如,树布局可以用来组织软件的包中类的层级结构。 像其他大多数布局一样,d3.layout.tree返回的是一个对象也是一个函数。也就是说:你可以像调用其他函数一样调用布局,并且这个布局函数有可以改变它的行为的附加方法。像D3里的其他类一样,布局遵循函数的链式模式,其中setter返回布局本身,允许在简单的语句中调用多个sette

  • 我在我的应用程序中使用MVVM模式。我有以下(简化版)VM类: 因此,一个Module2601_VM包含几个属性,以及Module2610_VM和ComPort_VM对象的列表。 我有一个MainModule_VM类中Module2601_VM对象的列表。 我想将这个Module2601集合及其子项绑定到树状视图中,并使用以下层次结构: 网关: 网关#0 COM#1 我的问题是,我的层次结构正常,