My company is building a graph-view editor for chatbots. We are using Cytoscape along with the cytoscape-cola
extension to accomplish this. One of the issues we are facing is dynamically adding new nodes to the graph without them overlapping with existing nodes on the graph.
I have looked through previous similar questions(listed below) but to no avail:
Cytoscape - handle locked nodesI tried the solution in there i.e. applying the layout only on the newly added nodes but they keep getting stacked in the centre of the screen.
Cytoscape - ignore locked nodesI tried the solution mentioned in here but regardless of locking the nodes in one go i.e. cy.nodes().lock()
or individually i.e. cy.nodes().forEach(node => node.lock())
, the locked nodes still keep moving. Also interesting thing to note here is that when locking nodes individually, the newly added node(s) are also locked regardless of whether or not I am locking in the call above or not.
I tried this solution as well but the locked nodes still move and the complete layout is changed - sometimes altogether, sometimes just a little.
This is currently what I am using to construct the graph:
const layoutConfig = {
name: "cola",
handleDisconnected: true,
animate: true,
avoidOverlap: true,
infinite: false,
unconstrIter: 1,
userConstIter: 0,
allConstIter: 1,
ready: e => {
e.cy.fit()
e.cy.center()
}
}
this.graph = Cytoscape({ ... })
this.layout = this.grapg.makeLayout(layoutConfig)
this.layout.run();
This is what I am using to add new node(s) to the graph:
const addElements = (elements: ElementSingular | ElementMultiple) => {
this.graph.nodes().forEach(node => {
node.lock();
})
this.graph.add(elements)
this.layout = this.graph.makeLayout(layoutConfig)
this.layout.on("layoutready", () => {
this.nodes().forEach(node => {
node.unlock();
})
})
this.layout.run()
this.graph.nodes().forEach(node => {
node.unlock();
})
}
I'd like to do one of the following:
11.3. The simplest method to manually organize a network is to click on a node and drag it. All of the selected nodes are moved together. In addition to the ability to click on a node and drag it to a new position, Cytoscape now has the ability to move nodes using the arrow keys on the keyboard.
Passthrough MappingThe values of network column data are passed directly through to properties. A passthrough mapping is typically used to specify node/edge labels. For example, a passthrough mapping can label all nodes with their common gene names.
Hold left-click and drag to select multiple nodes · Issue #810 · cytoscape/cytoscape.
Edit: Is this what you were looking for? https://output.jsbin.com/hokineluwo
Edit: I didn't saw before, but you are also unlocking
the nodes right after the layout call, Cola is async, the run only kicks-off the process. Remove that code and only use the layoutstop
method.
I don't remember correctly, but i think that cola keeps moving the elements after the layoutready
. From their code:
// trigger layoutready when each node has had its position set at least once
There is a layoutstop
event that you could use (and cytoscape-cola uses too).
From the docs (emphasis is mine):
layoutready : when a layout has set initial positions for all the nodes (but perhaps not final positions)
layoutstop : when a layout has finished running completely or otherwise stopped running
I would try to remove that callback and inspect if it gives good results. Also, you should try to reproduce it here: http://jsbin.com/fiqugiq
It makes it easier for others (even the authors) to play with it and see if you have found a bug or not.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With