cytoscape.js 和 dagre 导致一个节点位置尴尬

cytoscape.js and dagre result in one node positioned awkwardly

鉴于下面的 cytoscape.js 片段,使用 dagre 布局,谁能解释为什么节点 2 将自己定位在右下角而不是像其他节点一样按顺序排列?

var cy = cytoscape({
  container: document.getElementById('cy'),
  elements: [{
      data: {
        id: 1477,
        label: "Heading",
      },
    },
    {
      data: {
        id: 1483,
        label: "Number 2",
        parent: 1479,
      },
    },
    {
      data: {
        id: 1479,
        label: "Group",
      },
    },
    {
      data: {
        id: 1478,
        label: "Number 0",
        parent: 1479,
      },
    },
    {
      data: {
        id: 1480,
        source: 1477,
        target: 1478,
        minLen: 1,
      },
    },
    {
      data: {
        id: 1484,
        source: 1481,
        target: 1483,
        minLen: 1,
      },
    },
    {
      data: {
        id: 1481,
        label: "Number 1",
        parent: 1479,
      },
    },
    {
      data: {
        id: 1482,
        source: 1478,
        target: 1481,
        minLen: 1,
      },
    },
    {
      data: {
        id: 1487,
        label: "Number 4",
        parent: 1479,
      },
    },
    {
      data: {
        id: 1485,
        label: "Number 3",
        parent: 1479,
      },
    },
    {
      data: {
        id: 1486,
        source: 1483,
        target: 1485,
        minLen: 1,
      },
    },
    {
      data: {
        id: 1488,
        source: 1485,
        target: 1487,
        minLen: 1,
      },
    },
    {
      data: {
        id: 1490,
        source: 1487,
        target: 1489,
        minLen: 1,
      },
    },
    {
      data: {
        id: 1489,
        label: "Number 5",
        parent: 1479,
      },
    },
    {
      data: {
        id: 1491,
        label: "Final",
      },
    },
    {
      data: {
        id: 1492,
        source: 1489,
        target: 1491,
        minLen: 1,
      },
    },
  ],
  layout: {
    name: 'dagre',
    'nodeSep': 25,
    'rankSep': 10,
  },
  style: [{
      selector: 'node',
      style: {
        label: 'data(label)',
        'text-valign': 'center',
        'text-halign': 'right',
        'text-margin-x': '-155',
        'text-wrap': 'wrap',
        'text-max-width': 150,
        'width': 180,
        'background-fit': 'contain',
        'shape': 'roundrectangle',
        'background-opacity': 0,
        'background-position-x': 0,
        'height': 24,
        'border-width': 1,
        'padding-right': 5,
        'padding-left': 5,
        'padding-top': 5,
        'padding-bottom': 5,
        'text-events': 'yes',
        'font-size': 12,
      }
    },
    {
      selector: 'edge',
      style: {
        'width': 1,
        'curve-style': 'bezier',
        'line-color': 'black',
        'line-style': 'solid',
        'target-arrow-shape': 'triangle-backcurve',
        'target-arrow-color': 'black',
        'text-rotation': 'autorotate',
        'label': 'data(label)',
      }
    },
    {
      selector: '$node > node',
      style: {
        'text-rotation': '-90deg',
        'text-halign': 'left',
        'text-margin-x': -10,
        'text-margin-y': -40,
      }
    },
    {
      selector: '.Badge',
      style: {
        'border-width': 3,
      }
    },
  ],
  minZoom: 0.5,
  maxZoom: 1.5,
  zoomingEnabled: true,
  userZoomingEnabled: false,
  autoungrabify: false,
  autounselectify: true,
});
body { 
  font: 14px helvetica neue, helvetica, arial, sans-serif;
}

#cy {
  height: 100%;
  width: 100%;
  position: absolute;
  left: 0;
  top: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.2.5/cytoscape.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/dagre/0.8.5/dagre.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/cytoscape-dagre@2.2.2/cytoscape-dagre.min.js"></script>


<div id="cy"></div>

稍微重新安排一下,您就可以轻松地让它发挥作用。通常,最好按节点和边对元素进行分组,也按升序排列。这提高了可读性,并在这种情况下防止了不一致的布局。

我认为这里的问题源于在相应节点(节点 Number 2)出现之前将边添加到图中。

这是工作代码:

var cy = cytoscape({
  container: document.getElementById('cy'),
  elements: {

    nodes: [{
        data: {
          id: 1477,
          label: "Heading",
        },
      },
      {
        data: {
          id: 1479,
          label: "Group",
        },
      },
      {
        data: {
          id: 1478,
          label: "Number 0",
          parent: 1479,
        },
      },
      {
        data: {
          id: 1481,
          label: "Number 1",
          parent: 1479,
        },
      },
      {
        data: {
          id: 1483,
          label: "Number 2",
          parent: 1479,
        },
      },
      {
        data: {
          id: 1485,
          label: "Number 3",
          parent: 1479,
        },
      },
      {
        data: {
          id: 1487,
          label: "Number 4",
          parent: 1479,
        },
      },
      {
        data: {
          id: 1489,
          label: "Number 5",
          parent: 1479,
        },
      },
      {
        data: {
          id: 1491,
          label: "Final",
        },
      },
    ],
    edges: [{
        data: {
          id: 1480,
          source: 1477,
          target: 1478,
          minLen: 1,
        },
      },
      {
        data: {
          id: 1482,
          source: 1478,
          target: 1481,
          minLen: 1,
        },
      },
      {
        data: {
          id: 1484,
          source: 1481,
          target: 1483,
          minLen: 1,
        },
      },
      {
        data: {
          id: 1486,
          source: 1483,
          target: 1485,
          minLen: 1,
        },
      },
      {
        data: {
          id: 1488,
          source: 1485,
          target: 1487,
          minLen: 1,
        },
      },
      {
        data: {
          id: 1490,
          source: 1487,
          target: 1489,
          minLen: 1,
        },
      },

      {
        data: {
          id: 1492,
          source: 1489,
          target: 1491,
          minLen: 1,
        },
      }
    ]
  },
  layout: {
    name: 'dagre',
    'nodeSep': 25,
    'rankSep': 10,
  },
  style: [{
      selector: 'node',
      style: {
        label: 'data(label)',
        'text-valign': 'center',
        'text-halign': 'right',
        'text-margin-x': '-155',
        'text-wrap': 'wrap',
        'text-max-width': 150,
        'width': 180,
        'background-fit': 'contain',
        'shape': 'roundrectangle',
        'background-opacity': 0,
        'background-position-x': 0,
        'height': 24,
        'border-width': 1,
        'padding-right': 5,
        'padding-left': 5,
        'padding-top': 5,
        'padding-bottom': 5,
        'text-events': 'yes',
        'font-size': 12,
      }
    },
    {
      selector: 'edge',
      style: {
        'width': 1,
        'curve-style': 'bezier',
        'line-color': 'black',
        'line-style': 'solid',
        'target-arrow-shape': 'triangle-backcurve',
        'target-arrow-color': 'black',
        'text-rotation': 'autorotate',
        'label': 'data(label)',
      }
    },
    {
      selector: '$node > node',
      style: {
        'text-rotation': '-90deg',
        'text-halign': 'left',
        'text-margin-x': -10,
        'text-margin-y': -40,
      }
    },
    {
      selector: '.Badge',
      style: {
        'border-width': 3,
      }
    },
  ],
  minZoom: 0.5,
  maxZoom: 1.5,
  zoomingEnabled: true,
  userZoomingEnabled: false,
  autoungrabify: false,
  autounselectify: true,
});
body {
  font: 14px helvetica neue, helvetica, arial, sans-serif;
}

#cy {
  height: 100%;
  width: 100%;
  position: absolute;
  left: 0;
  top: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.2.5/cytoscape.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/dagre/0.8.5/dagre.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/cytoscape-dagre@2.2.2/cytoscape-dagre.min.js"></script>


<div id="cy"></div>