0

I want to launch a new springy layout when a node is moved. To do so, I listen to the "position" event on nodes and set a "moving" flag on that node and turn off position change notification. Then when the node is freed, I check if it has moved and if so I start to layout and I set a variable to know a layout is currently running.

Here are the methods I used:

var layouting = false;    

var relayout = function() {
    if (layouting === false) {
        layouting = true;           
        cy.layout(forceFieldLayout);
    }
}

var nodeMoving = function(e) {
    cy.off('position', 'node', nodeMoving);
    e.cyTarget.data("moving", true);
}

cy.on("free", 'node', function(e) {
        if (e.cyTarget.data("moving") === true) {
            e.cyTarget.data("moving", false)
            relayout();
         }
 });

In the layoutstop event, I was turning back on the position notification but position events were still raised thus starting a whole new layout again resulting in an infinite loop.

I resolved the issue by using a timeout before turning the notification back on.

cy.on("layoutstop", function() {    
    window.setTimeout( function(){
                    layouting = false;
                    cy.on('position', 'node', nodeMoving);
                }, 250);
);

Why do I need the timeout?

Melanie
  • 1,198
  • 2
  • 17
  • 42

1 Answers1

1

I can only reproduce this on Springy, which is an inferior layout to all other included physics sim layouts in terms of both runtime and visual results.

(1) I suggest you don't use Springy. It's included only for the sake of completeness (and a few people like it, though I can't imagine why).

(2) https://github.com/cytoscape/cytoscape.js/issues/865

maxkfranz
  • 11,896
  • 1
  • 27
  • 36