cytoscape-cose-bilkent
Advanced tools
Comparing version 1.5.1 to 1.5.2
{ | ||
"name": "cytoscape-cose-bilkent", | ||
"version": "1.5.1", | ||
"version": "1.5.2", | ||
"description": "The CoSE layout for Cytoscape.js by Bilkent", | ||
@@ -5,0 +5,0 @@ "main": "src/index.js", |
@@ -55,2 +55,4 @@ cytoscape-cose-bilkent | ||
}, | ||
// number of ticks per frame; higher is faster but more jerky | ||
refresh: 30, | ||
// Whether to fit the network view after when done | ||
@@ -57,0 +59,0 @@ fit: true, |
@@ -14,5 +14,3 @@ 'use strict'; | ||
register( cytoscape ); | ||
} | ||
if( typeof define !== 'undefined' && define.amd ){ | ||
} else if( typeof define !== 'undefined' && define.amd ){ | ||
define( [], register ); | ||
@@ -19,0 +17,0 @@ } |
@@ -112,55 +112,70 @@ var FDLayout = require('./FDLayout'); | ||
console.log("Classic CoSE layout finished after " + | ||
this.totalIterations + " iterations"); | ||
return true; | ||
}; | ||
CoSELayout.prototype.runSpringEmbedder = function () { | ||
var lastFrame = new Date().getTime(); | ||
var initialAnimationPeriod = 25; | ||
var animationPeriod = initialAnimationPeriod; | ||
do | ||
CoSELayout.prototype.tick = function() { | ||
this.totalIterations++; | ||
if (this.totalIterations === this.maxIterations) { | ||
return true; // Layout is not ended return true | ||
} | ||
if (this.totalIterations % FDLayoutConstants.CONVERGENCE_CHECK_PERIOD == 0) | ||
{ | ||
this.totalIterations++; | ||
if (this.totalIterations % FDLayoutConstants.CONVERGENCE_CHECK_PERIOD == 0) | ||
if (this.isConverged()) | ||
{ | ||
if (this.isConverged()) | ||
{ | ||
break; | ||
} | ||
return true; // Layout is not ended return true | ||
} | ||
this.coolingFactor = this.initialCoolingFactor * | ||
((this.maxIterations - this.totalIterations) / this.maxIterations); | ||
animationPeriod = Math.ceil(initialAnimationPeriod * Math.sqrt(this.coolingFactor)); | ||
this.coolingFactor = this.initialCoolingFactor * | ||
((this.maxIterations - this.totalIterations) / this.maxIterations); | ||
this.animationPeriod = Math.ceil(this.initialAnimationPeriod * Math.sqrt(this.coolingFactor)); | ||
} | ||
this.totalDisplacement = 0; | ||
this.graphManager.updateBounds(); | ||
this.calcSpringForces(); | ||
this.calcRepulsionForces(); | ||
this.calcGravitationalForces(); | ||
this.moveNodes(); | ||
this.animate(); | ||
return false; // Layout is not ended yet return false | ||
}; | ||
CoSELayout.prototype.getPositionsData = function() { | ||
var allNodes = this.graphManager.getAllNodes(); | ||
var pData = {}; | ||
for (var i = 0; i < allNodes.length; i++) { | ||
var rect = allNodes[i].rect; | ||
var id = allNodes[i].id; | ||
pData[id] = { | ||
id: id, | ||
x: rect.getCenterX(), | ||
y: rect.getCenterY(), | ||
w: rect.width, | ||
h: rect.height | ||
}; | ||
} | ||
return pData; | ||
}; | ||
CoSELayout.prototype.runSpringEmbedder = function () { | ||
this.initialAnimationPeriod = 25; | ||
this.animationPeriod = this.initialAnimationPeriod; | ||
var layoutEnded = false; | ||
// If aminate option is 'during' signal that layout is supposed to start iterating | ||
if ( FDLayoutConstants.ANIMATE === 'during' ) { | ||
this.emit('layoutstarted'); | ||
} | ||
else { | ||
// If aminate option is 'during' tick() function will be called on index.js | ||
while (!layoutEnded) { | ||
layoutEnded = this.tick(); | ||
} | ||
this.totalDisplacement = 0; | ||
this.graphManager.updateBounds(); | ||
this.calcSpringForces(); | ||
this.calcRepulsionForces(); | ||
this.calcGravitationalForces(); | ||
this.moveNodes(); | ||
this.animate(); | ||
if (FDLayoutConstants.ANIMATE === 'during' && this.totalIterations % animationPeriod == 0) { | ||
var allNodes = this.graphManager.getAllNodes(); | ||
var pData = {}; | ||
for (var i = 0; i < allNodes.length; i++) { | ||
var rect = allNodes[i].rect; | ||
var id = allNodes[i].id; | ||
pData[id] = { | ||
id: id, | ||
x: rect.getCenterX(), | ||
y: rect.getCenterY(), | ||
w: rect.width, | ||
h: rect.height | ||
}; | ||
} | ||
this.emit('iterate', pData); // Emit the data for during layout animation | ||
} | ||
} | ||
while (this.totalIterations < this.maxIterations); | ||
this.graphManager.updateBounds(); | ||
}; | ||
@@ -167,0 +182,0 @@ |
@@ -41,2 +41,4 @@ 'use strict'; | ||
}, | ||
// number of ticks per frame; higher is faster but more jerky | ||
refresh: 30, | ||
// Whether to fit the network view after when done | ||
@@ -127,49 +129,6 @@ fit: true, | ||
var options = this.options; | ||
var animationData; // Data to be rendered during animation | ||
var idToLNode = this.idToLNode = {}; | ||
var layout = this.layout = new CoSELayout(); | ||
var self = this; | ||
var animationStarted = false; | ||
/* | ||
* Reposition nodes in iterations animatedly | ||
*/ | ||
var iterateAnimated = function () { | ||
options.eles.nodes().positions(function (ele, i) { | ||
if (typeof ele === "number") { | ||
ele = i; | ||
} | ||
if (ele.scratch('coseBilkent') && ele.scratch('coseBilkent').dummy_parent_id) { | ||
var dummyParent = ele.scratch('coseBilkent').dummy_parent_id; | ||
return { | ||
x: dummyParent.x, | ||
y: dummyParent.y | ||
}; | ||
} | ||
var theId = ele.data('id'); | ||
var pNode = animationData[theId]; | ||
var temp = this; | ||
while (pNode == null) { | ||
temp = temp.parent()[0]; | ||
pNode = animationData[temp.id()]; | ||
animationData[theId] = pNode; | ||
} | ||
return { | ||
x: pNode.x, | ||
y: pNode.y | ||
}; | ||
}); | ||
if (options.fit) | ||
options.cy.fit(options.eles.nodes(), options.padding); | ||
if (!ready) { | ||
ready = true; | ||
self.cy.one('layoutready', options.ready); | ||
self.cy.trigger({type: 'layoutready', layout: self}); | ||
} | ||
frameId = requestAnimationFrame(iterateAnimated); | ||
}; | ||
this.cy = this.options.cy; | ||
@@ -187,13 +146,2 @@ | ||
/* | ||
* Listen 'iterate' event and when it is signaled position the nodes with their current positions on that iteration to have 'during' layout animation. | ||
*/ | ||
layout.addListener('iterate', function (_animationData) { | ||
animationData = _animationData; | ||
if (!animationStarted && options.animate && options.animate !== 'end') { | ||
iterateAnimated(); | ||
animationStarted = true; | ||
} | ||
}); | ||
if (!this.options.tile) { | ||
@@ -228,44 +176,106 @@ this.processChildrenList(this.root, this.getTopMostNodes(nodes), layout); | ||
layout.runLayout(); | ||
/* | ||
* Reposition nodes in iterations animatedly | ||
*/ | ||
var iterateAnimated = function () { | ||
// Thigs to perform after nodes are repositioned on screen | ||
var afterReposition = function() { | ||
if (options.fit) { | ||
options.cy.fit(options.eles.nodes(), options.padding); | ||
} | ||
if (!ready) { | ||
ready = true; | ||
self.cy.one('layoutready', options.ready); | ||
self.cy.trigger({type: 'layoutready', layout: self}); | ||
} | ||
}; | ||
var ticksPerFrame = self.options.refresh; | ||
var isDone; | ||
for( var i = 0; i < ticksPerFrame && !isDone; i++ ){ | ||
isDone = self.layout.tick(); | ||
} | ||
// If layout is done | ||
if (isDone) { | ||
if (self.options.tile) { | ||
self.postLayout(); | ||
} | ||
self.options.eles.nodes().positions(getPositions); | ||
afterReposition(); | ||
// trigger layoutstop when the layout stops (e.g. finishes) | ||
self.cy.one('layoutstop', self.options.stop); | ||
self.cy.trigger('layoutstop'); | ||
if (frameId) { | ||
cancelAnimationFrame(frameId); | ||
} | ||
self.options.eles.nodes().removeScratch('coseBilkent'); | ||
ready = false; | ||
return; | ||
} | ||
var animationData = self.layout.getPositionsData(); // Get positions of layout nodes note that all nodes may not be layout nodes because of tiling | ||
// Position nodes, for the nodes who are not passed to layout because of tiling return the position of their dummy compound | ||
options.eles.nodes().positions(function (ele, i) { | ||
if (typeof ele === "number") { | ||
ele = i; | ||
} | ||
if (ele.scratch('coseBilkent') && ele.scratch('coseBilkent').dummy_parent_id) { | ||
var dummyParent = ele.scratch('coseBilkent').dummy_parent_id; | ||
return { | ||
x: dummyParent.x, | ||
y: dummyParent.y | ||
}; | ||
} | ||
var theId = ele.data('id'); | ||
var pNode = animationData[theId]; | ||
var temp = this; | ||
while (pNode == null) { | ||
temp = temp.parent()[0]; | ||
pNode = animationData[temp.id()]; | ||
animationData[theId] = pNode; | ||
} | ||
return { | ||
x: pNode.x, | ||
y: pNode.y | ||
}; | ||
}); | ||
afterReposition(); | ||
frameId = requestAnimationFrame(iterateAnimated); | ||
}; | ||
if (this.options.tile) { | ||
this.postLayout(); | ||
} | ||
/* | ||
* Listen 'layoutstarted' event and start animated iteration if animate option is 'during' | ||
*/ | ||
layout.addListener('layoutstarted', function () { | ||
if (self.options.animate === 'during') { | ||
frameId = requestAnimationFrame(iterateAnimated); | ||
} | ||
}); | ||
layout.runLayout(); // Run cose layout | ||
/* | ||
* If animate option is not 'during' ('end' or false) use layoutPositions(). | ||
* If it is 'during' layoutPositions() will be one more unintended animation at the end. | ||
* Therefore in that case we do things manually. | ||
* If animate option is not 'during' ('end' or false) perform these here (If it is 'during' similar things are already performed) | ||
*/ | ||
if(this.options.animate !== 'during'){ | ||
this.options.eles.nodes().layoutPositions(this, this.options, getPositions); | ||
} | ||
else { | ||
setTimeout(function() { | ||
self.options.eles.nodes().positions(getPositions); | ||
if (self.options.fit) | ||
self.options.cy.fit(self.options.eles.nodes(), self.options.padding); | ||
//trigger layoutready when each node has had its position set at least once | ||
if (!ready) { | ||
self.cy.one('layoutready', self.options.ready); | ||
self.cy.trigger('layoutready'); | ||
} | ||
// trigger layoutstop when the layout stops (e.g. finishes) | ||
self.cy.one('layoutstop', self.options.stop); | ||
self.cy.trigger('layoutstop'); | ||
if (frameId) { | ||
cancelAnimationFrame(frameId); | ||
} | ||
}, 1000/60); | ||
if (self.options.tile) { | ||
self.postLayout(); | ||
} | ||
self.options.eles.nodes().layoutPositions(self, self.options, getPositions); // Use layout positions to reposition the nodes it considers the options parameter | ||
self.options.eles.nodes().removeScratch('coseBilkent'); | ||
ready = false; | ||
}, 0); | ||
} | ||
this.options.eles.nodes().removeScratch('coseBilkent'); | ||
animationStarted = false; | ||
ready = false; | ||
return this; // chaining | ||
@@ -272,0 +282,0 @@ }; |
@@ -122,4 +122,2 @@ var LayoutConstants = require('./LayoutConstants'); | ||
var excTime = endTime - startTime; | ||
console.log("Total execution time: " + excTime + " miliseconds."); | ||
} | ||
@@ -126,0 +124,0 @@ } |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
595583
9839
100