Я пытаюсь использовать макет Cytoscape cola для рендеринга графика, который должен применять силовой макет при его использовании (поэтому при перетаскивании узлов они должны действовать так, как будто присутствует некоторая гравитация). Соответствующие библиотеки:
- https://github.com/cytoscape/cytoscape.js
- https://github.com/tgdwyer/WebCola
- https://github.com/cytoscape/cytoscape.js-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/[email protected]/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>
Это ошибка или я что-то не так делаю? Кто-нибудь знает, как остановить и перезапустить макет без изменения положения узлов?
Большое спасибо, Джесси