Cytoscape Cola Layout:如何在不改变位置的情况下重新开始布局?

Cytoscape Cola Layout: How to restart the layout without any change of positions?

我正在尝试使用 Cytoscape cola 布局来渲染一个图形,该图形在使用时应应用力导向布局(因此,当四处拖动节点时,它们应该表现得好像有一些重力)。 相关图书馆:

我的第一个问题是通过 add(node) 将节点添加到图形中并没有将它们包含在可乐布局算法中。我发现的唯一方法是破坏布局,重新初始化并重新启动它。但是在某些情况下这会导致节点跳转。

我认为这是因为我完全破坏了旧布局,但是在设置一个最小示例时,我意识到即使只是调用 layout.stop()layout.run() 也会导致节点被重新定位。

在下面的例子中,只有一个节点。通过拖放移动节点,然后按“停止”按钮,然后按“开始”按钮使节点跳回到其初始位置:

document.addEventListener('DOMContentLoaded', function(){
        
  // Register cola layout
  cytoscapeCola(cytoscape);

  var nodes = [{ data: { id: 1, name: 1 } }]
  var edges = [];

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

    style: [
      {
        selector: 'node[name]',
        style: {
          'content': 'data(name)'
        }
      },

      {
        selector: 'edge',
        style: {
          'curve-style': 'bezier',
          'target-arrow-shape': 'triangle'
        }
      },
    ],

    elements: {
      nodes: nodes,
      edges: edges
    }
  });

  var layout = cy.layout({
    name: 'cola',
    infinite: true,
    fit: false,
  });
  layout.run();

  document.querySelector('#start').addEventListener('click', function() {
    layout.run();
  });

  document.querySelector('#stop').addEventListener('click', function() {
    layout.stop();
  });

  document.querySelector('#add-node').addEventListener('click', function() {
    var id = Math.random();
    cy.add({ group: 'nodes', data: { id: id, name: id } });
    cy.add({ group: 'edges', data: { source: id, target: _.head(nodes).data.id } });
    layout.stop();
    layout.destroy();
    layout = cy.layout({
      name: 'cola',
      infinite: true,
      fit: false,
    });
    layout.run();
  });

});
body {
  font-family: helvetica neue, helvetica, liberation sans, arial, sans-serif;
  font-size: 14px;
}

#cy {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  right: 0;
  z-index: 999;
}

h1 {
  opacity: 0.5;
  font-size: 1em;
  font-weight: bold;
}

#buttons {
  position: absolute;
  right: 0;
  bottom: 0;
  z-index: 99999;
}
<!DOCTYPE>

<html>

  <head>
    <title>cytoscape-edgehandles.js demo for infinite layout</title>

    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">

    <script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>

    <script src="https://unpkg.com/webcola/WebCola/cola.min.js"></script> 
    <script src="https://cdn.jsdelivr.net/npm/cytoscape-cola@2.4.0/cytoscape-cola.min.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.js"></script>
    <script src="cytoscape-edgehandles.js"></script>
    
    </head>

  <body>
    <h1>cytoscape-edgehandles demo with an infinite layout</h1>
    <div id="cy"></div>
    <div id="buttons">
      <button id="start">Start</button>
      <button id="stop">Stop</button>
      <button id="add-node">Add Node</button>
    </div>
  </body>

</html>

这是一个错误还是我做错了什么?有谁知道如何在不改变节点位置的情况下停止和重新启动布局?

非常感谢, 杰西

好的,实际上你非常亲密@Stephan。 问题是 WebCola 在默认调用 start 时将节点居中: https://github.com/tgdwyer/WebCola/blob/78a24fc0dbf0b4eb4a12386db9c09b087633267d/src/layout.ts#L504

WebCola 的 cytoscape 包装器目前不支持这个选项,所以我 fork 了它并自己添加了这个选项: https://github.com/deje1011/cytoscape.js-cola/commit/f357b97aba900327e12f97b1530c4df624ff9d61

我会在某个时候打开一个拉取请求。

现在你可以像这样顺利重启布局了:

layout.stop();
layout.destroy(); // cleanup event listeners
layout = graph.layout({ name: 'cola', infinite: true, fit: false, centerGraph: false });
layout.run()

这样,节点保持它们的位置