【问题标题】:Why are my embedded JointJS elements overlapping?为什么我嵌入的 JointJS 元素重叠?
【发布时间】:2016-03-30 16:19:38
【问题描述】:

我正在研究一个 JointJS 图,使用 DirectedGraph 来处理布局,我正在尝试实现类似于下图的效果。我需要将节点(A、B、C、D、E、F、G、H、I、J)“概述”或包含在单独的节点(Foo、Bar、Hmm)中。当我将所有元素添加到图表中时,一切都在彼此之上。但是,如果我不在区域之间添加顶点,则所有元素的布局都正确,但没有连接区域的顶点。

根据下面的代码,我做错了什么?节点(A、B、C、D、E、F、G、H、I、J)是否因为未连接到图的其余部分而导致错误?

非常感谢您提供的任何反馈。

var graph = new joint.dia.Graph;
var paper = new joint.dia.Paper({
    el: $('#paper');
    width: 2000,
    height: 2000,
    gridSize: 1,
    model: graph
});

var regions = [ makeRegion('Foo'), makeRegion('Bar'), makeRegion('Hmm')];
var nodes = [
    makeNode('A'),
    makeNode('B'),
    makeNode('C'),
    makeNode('D'),
    makeNode('F'),
    makeNode('G'),
    makeNode('H'),
    makeNode('I'),
    makeNode('J'),
];
regions[0].embed(nodes[0]).embed(nodes[1]).embed(nodes[2]);
regions[1].embed(nodes[3]).embed(nodes[4]).embed(nodes[5]);
regions[2].embed(nodes[6]).embed(nodes[7]).embed(nodes[8]);
var vertices = [
    connect(regions[0], regions[1]),
    connect(regions[1], regions[2]),
    connect(regions[2], regions[0])
    ];
paper.addCells(regions.concat(nodes).concat(vertices));
joint.layout.DirectedGraph.layout(paper, {
    rankDir: 'LR',
    marginX: 30,
    marginY: 30,
    clusterPadding: {
        top: 30,
        left: 10,
        right: 10,
        bottom: 10
    }
});

function makeNode(name) {
    return new joint.shapes.basic.Rect({
        size: {
            width: 35,
            height: 35
        },
        attrs: {
            text: {
                text: name
            }
        }
    });
}

function connect(a, b) {
    return new joint.shapes.fsa.Arrow({
        source: { id: a.id },
        target: { id: b.id }
    });
}

function makeRegion(name) {
    return new joint.shapes.basic.Rect({
        size: {
            width: 300,
            height: 200
        },
        attrs: {
            text: {
                text: name
            }
        }
    });
}

编辑:

虽然我从未找到解决此问题的好方法,但我确实发现通过一些额外的工作可以实现这一目标。它假设您的图表不太复杂,区域之间的边很少。

如果我单独添加边,在所有节点都添加到图中之后,它会正常工作。然而,定向布局并没有完全按预期工作。我最初使用joint.layout.DirectedGraph.layout() 以便它对齐内部节点,然后我重新定位外部区域。最后,我添加了边缘,这会产生类似于上图的结果。

这是我如何实现这一目标的粗略概述:

var graph = new joint.dia.Graph;
var paper = new joint.dia.Paper({
    el: $('#paper');
    width: 2000,
    height: 2000,
    gridSize: 1,
    model: graph
});

var regions = [ makeRegion('Foo'), makeRegion('Bar'), makeRegion('Hmm')];
var nodes = [
    makeNode('A'),
    makeNode('B'),
    makeNode('C'),
    makeNode('D'),
    makeNode('F'),
    makeNode('G'),
    makeNode('H'),
    makeNode('I'),
    makeNode('J'),
];
regions[0].embed(nodes[0]).embed(nodes[1]).embed(nodes[2]);
regions[1].embed(nodes[3]).embed(nodes[4]).embed(nodes[5]);
regions[2].embed(nodes[6]).embed(nodes[7]).embed(nodes[8]);

paper.addCells(regions.concat(nodes));
joint.layout.DirectedGraph.layout(paper, {
    rankDir: 'LR',
    marginX: 30,
    marginY: 30,
    clusterPadding: {
        top: 30,
        left: 10,
        right: 10,
        bottom: 10
    }
});

var vertices = [
    connect(regions[0], regions[1]),
    connect(regions[1], regions[2]),
    connect(regions[2], regions[0])
    ];
repositionRegions();
// Add the edges after all the nodes are in their final position
graph.addCells(vertices);

function repositionRegions() {
    // Move regions to where you want them
}

function makeNode(name) {
    return new joint.shapes.basic.Rect({
        size: {
            width: 35,
            height: 35
        },
        attrs: {
            text: {
                text: name
            }
        }
    });
}

function connect(a, b) {
    return new joint.shapes.fsa.Arrow({
        source: { id: a.id },
        target: { id: b.id }
    });
}

function makeRegion(name) {
    return new joint.shapes.basic.Rect({
        size: {
            width: 300,
            height: 200
        },
        attrs: {
            text: {
                text: name
            }
        }
    });
}

【问题讨论】:

    标签: javascript jointjs


    【解决方案1】:

    这是 Dagre-D3 的一个已知问题:Automatic layout does not work on hierarchical diagrams with links with parent

    作为一种解决方法,您可以省略区域之间的链接(在您的问题版本中建议),或者您可以做一些额外的工作,这将很好地适用于任意数量的节点:

    1. 分别布局每组子节点:

      var fooChildren = [nodes[0], nodes[1], nodes[2]];
      var barChildren = [nodes[3], nodes[4], nodes[5]];
      var hmmChildren = [nodes[6], nodes[7], nodes[8]];
      var children = [fooChildren, barChildren, hmmChildren];
      
      for(var i = 0; i < children.length; i++)
          joint.layout.DirectedGraph.layout(children[i]);
      
    2. 为每个区域创建一个辅助克隆区域。

      var clones = [];
      for(var i = 0; i < regions.length; i++) {
          var clone = regions[i].clone();
          graph.addCell(clone);
          clones.push(clone);
      }
      
    3. 将相应的节点设置为其克隆区域。

      for(var i = 0; i < children.length; i ++)
          for(var k = 0; k < children[i].length; k++)
              clones[i].embed(children[i][k]);
      
    4. 使每个克隆区域适合其子区域的大小,并根据克隆区域的大小调整原始区域的大小。

      for(var i = 0; i < clones.length; i++) {
          clones[i].fitEmbeds(padding: { top: 30, left: 10, right: 10, bottom: 10 });
          regions[i].resize(clones[i].getBBox().width, clones[i].getBBox().height);
      }
      
    5. 布局图表。

      joint.layout.DirectedGraph.layout(graph, {
          rankDir: 'LR',
          marginX: 30,
          marginY: 30,
          clusterPadding: {
              top: 30,
              left: 10,
              right: 10,
              bottom: 10
          }
      });
      
    6. 将克隆的区域平移到其原始区域的位置(子区域将相应地平移)。

      for(var i = 0; i < clones.length; i++) {
          var dx = regions[i].getBBox().x - clones[i].getBBox().x;
          var dy = regions[i].getBBox().y - clones[i].getBBox().y;
          clones[i].translate(dx, dy);
      }
      
    7. 删除克隆区域并将子区域设置为原始区域。

      for(var i = 0; i < regions.length; i++) {
          clones[i].remove();
      
          for(var j = 0; j < children[i].length; j++)
              regions[i].embed(children[i][j]);
      }
      

    希望这有助于提供替代解决方案。

    【讨论】:

    • 你能提供一个有效的 JSFiddle 链接和这个解决方案吗?我已经尝试过了,我收到了Uncaught TypeError: Cannot read property 'isElement' of undefined 之类的错误
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-18
    相关资源
    最近更新 更多