Cytoscape.js dynamically add nodes without moving the others
Asked Answered
O

1

4

I am working on an application that fetches data from a database and I would like to show them as graph.

I managed the "tap" event on a node by showing their neighbors (nodes and connection links).

The problem is that, every time I want to show the neighbors, all the graph is re-rendered and if some nodes were moved before, they lose their previous position.

Is there a way to add only the neighbors without affecting the position of the node already present in the layout?

Important: the constraint is that all the nodes should be "movable": the number of nodes in the graph can, easily, increase and I would like to have the availability to move/organize them without losing the result when I add new ones (by clicking on a node)

I am using cola-layout in my project.

Here the way I managed to add neighbors:

function addNeighbour(node, link) {
    cy.startBatch();
    addNode(link.otherNode.type, link.otherNode.name, link.otherNode.properties);
    cy.add([
      {
        group: 'edges',
        data:
        {
          id: node + ":" + link.type + ":" + link.otherNode.type + ":" + link.otherNode.name,
          source: source,
          target: target,
          type: link.type,
          properties: linkproperties
        }
      }
    ]);
    refreshLayout()
    cy.endBatch();
  }
}

var layoutOpts = {
    name: 'cola',
    refresh: 2,
    edgeLength: 200,
    fit: false
}

function refreshLayout() {
    layout.stop();
    layout = cy.elements().makeLayout(layoutOpts);
    layout.run();
}

Thanks in advance

Otiose answered 5/3, 2019 at 13:11 Comment(3)
but the cola layout is specifically a force-directed physics layout, meaning that the nodes space themselves out. When you add new nodes, the desired behaviour IS to move the existing nodes, otherwise the layout doesn't make sense? The point is: cola is a well rounded extension for cytoscape and the options fit: false, infinity: true combined with a cy.center(); cy.fit(); after layoutready are optimal, so consider adding them to your project.Sclaff
Also, if you are persistent and don't want the physics to move your moved nodes, consider switching to another layout altogether.Sclaff
Hello Stephan, I tried with cy.center() and cy.fit() after the refreshLayout() with no luck. I already tried with another layout (like GRID, more static) but the problem becomes when a node has more than 1 neigbour: By clicking on a node that has, for example,5 neighbors, puts all the nodes (overlayed) at same place. This forces the user to move every node in the desire position. Moreover, when the graph grows and the user stars organizing the node for his purpose, a double click re-organize the node in a "grid" way invalidating the work previously carried out by the user. Any advices?Otiose
C
3

(1) You can lock a node to make its position immutable, via nodes.lock().

(2) You can run a layout on a subset of the graph to exclude certain elements, via eles.layout().

Either of these strategies can be used in general, or they can be used in tandem.

For your case, it sounds like you should use (1).

  • Lock the existing nodes.
  • Add the new nodes.
  • Run Cola on the entire graph.
  • When Cola is done, free the locked nodes.

Note, however, that this won't always give a good result. You could over-constrain the system. If you want a good layout result, it's probably best to just run the layout on everything without locking, as Stephan T. suggested.

Cathay answered 11/3, 2019 at 22:55 Comment(4)
Hello, I already tried with no success I found an alternative solution by not calling the "refreshLayout()" function and using the radiant to dispose all the neighbors around the source node. Thanks to all of you for the advices :)Otiose
@Otiose If you don't refresh the layout after adding a new node, doesn't it break the layout? I mean, wouldn't the node be added in one position unless you declare certain static position?Pyrology
@Cathay I'm also facing the same issue and I approached your advice above, but sometimes the added node are overlaid with other existing nodes if I locked the other ones before. Is it inevitable?Pyrology
This didn't work for me: github.com/cytoscape/cytoscape.js/discussions/3278Antirachitic

© 2022 - 2024 — McMap. All rights reserved.