|
|
|
@ -1,5 +1,5 @@
|
|
|
|
|
/**
|
|
|
|
|
* Springy v2.6.0
|
|
|
|
|
* Springy v2.7.1
|
|
|
|
|
*
|
|
|
|
|
* Copyright (c) 2010-2013 Dennis Hotson
|
|
|
|
|
*
|
|
|
|
@ -24,22 +24,24 @@
|
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
|
|
* OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
(function() {
|
|
|
|
|
// Enable strict mode for EC5 compatible browsers
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
|
// Establish the root object, `window` in the browser, or `global` on the server.
|
|
|
|
|
var root = this;
|
|
|
|
|
|
|
|
|
|
// The top-level namespace. All public Springy classes and modules will
|
|
|
|
|
// be attached to this. Exported for both CommonJS and the browser.
|
|
|
|
|
var Springy;
|
|
|
|
|
if (typeof exports !== 'undefined') {
|
|
|
|
|
Springy = exports;
|
|
|
|
|
(function (root, factory) {
|
|
|
|
|
if (typeof define === 'function' && define.amd) {
|
|
|
|
|
// AMD. Register as an anonymous module.
|
|
|
|
|
define(function () {
|
|
|
|
|
return (root.returnExportsGlobal = factory());
|
|
|
|
|
});
|
|
|
|
|
} else if (typeof exports === 'object') {
|
|
|
|
|
// Node. Does not work with strict CommonJS, but
|
|
|
|
|
// only CommonJS-like enviroments that support module.exports,
|
|
|
|
|
// like Node.
|
|
|
|
|
module.exports = factory();
|
|
|
|
|
} else {
|
|
|
|
|
Springy = root.Springy = {};
|
|
|
|
|
// Browser globals
|
|
|
|
|
root.Springy = factory();
|
|
|
|
|
}
|
|
|
|
|
}(this, function() {
|
|
|
|
|
|
|
|
|
|
var Springy = {};
|
|
|
|
|
|
|
|
|
|
var Graph = Springy.Graph = function() {
|
|
|
|
|
this.nodeSet = {};
|
|
|
|
@ -325,12 +327,13 @@
|
|
|
|
|
|
|
|
|
|
// -----------
|
|
|
|
|
var Layout = Springy.Layout = {};
|
|
|
|
|
Layout.ForceDirected = function(graph, stiffness, repulsion, damping, minEnergyThreshold) {
|
|
|
|
|
Layout.ForceDirected = function(graph, stiffness, repulsion, damping, minEnergyThreshold, maxSpeed) {
|
|
|
|
|
this.graph = graph;
|
|
|
|
|
this.stiffness = stiffness; // spring stiffness constant
|
|
|
|
|
this.repulsion = repulsion; // repulsion constant
|
|
|
|
|
this.damping = damping; // velocity damping factor
|
|
|
|
|
this.minEnergyThreshold = minEnergyThreshold || 0.01; //threshold used to determine render stop
|
|
|
|
|
this.maxSpeed = maxSpeed || Infinity; // nodes aren't allowed to exceed this speed
|
|
|
|
|
|
|
|
|
|
this.nodePoints = {}; // keep track of points associated with nodes
|
|
|
|
|
this.edgeSprings = {}; // keep track of springs associated with edges
|
|
|
|
@ -449,6 +452,9 @@
|
|
|
|
|
// Is this, along with updatePosition below, the only places that your
|
|
|
|
|
// integration code exist?
|
|
|
|
|
point.v = point.v.add(point.a.multiply(timestep)).multiply(this.damping);
|
|
|
|
|
if (point.v.magnitude() > this.maxSpeed) {
|
|
|
|
|
point.v = point.v.normalise().multiply(this.maxSpeed);
|
|
|
|
|
}
|
|
|
|
|
point.a = new Vector(0,0);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
@ -474,14 +480,14 @@
|
|
|
|
|
|
|
|
|
|
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; // stolen from coffeescript, thanks jashkenas! ;-)
|
|
|
|
|
|
|
|
|
|
Springy.requestAnimationFrame = __bind(root.requestAnimationFrame ||
|
|
|
|
|
root.webkitRequestAnimationFrame ||
|
|
|
|
|
root.mozRequestAnimationFrame ||
|
|
|
|
|
root.oRequestAnimationFrame ||
|
|
|
|
|
root.msRequestAnimationFrame ||
|
|
|
|
|
Springy.requestAnimationFrame = __bind(this.requestAnimationFrame ||
|
|
|
|
|
this.webkitRequestAnimationFrame ||
|
|
|
|
|
this.mozRequestAnimationFrame ||
|
|
|
|
|
this.oRequestAnimationFrame ||
|
|
|
|
|
this.msRequestAnimationFrame ||
|
|
|
|
|
(function(callback, element) {
|
|
|
|
|
root.setTimeout(callback, 10);
|
|
|
|
|
}), root);
|
|
|
|
|
this.setTimeout(callback, 10);
|
|
|
|
|
}), this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -639,14 +645,16 @@
|
|
|
|
|
* Renderer handles the layout rendering loop
|
|
|
|
|
* @param onRenderStop optional callback function that gets executed whenever rendering stops.
|
|
|
|
|
* @param onRenderStart optional callback function that gets executed whenever rendering starts.
|
|
|
|
|
* @param onRenderFrame optional callback function that gets executed after each frame is rendered.
|
|
|
|
|
*/
|
|
|
|
|
var Renderer = Springy.Renderer = function(layout, clear, drawEdge, drawNode, onRenderStop, onRenderStart) {
|
|
|
|
|
var Renderer = Springy.Renderer = function(layout, clear, drawEdge, drawNode, onRenderStop, onRenderStart, onRenderFrame) {
|
|
|
|
|
this.layout = layout;
|
|
|
|
|
this.clear = clear;
|
|
|
|
|
this.drawEdge = drawEdge;
|
|
|
|
|
this.drawNode = drawNode;
|
|
|
|
|
this.onRenderStop = onRenderStop;
|
|
|
|
|
this.onRenderStart = onRenderStart;
|
|
|
|
|
this.onRenderFrame = onRenderFrame;
|
|
|
|
|
|
|
|
|
|
this.layout.graph.addGraphListener(this);
|
|
|
|
|
}
|
|
|
|
@ -677,6 +685,8 @@
|
|
|
|
|
t.layout.eachNode(function(node, point) {
|
|
|
|
|
t.drawNode(node, point.p);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (t.onRenderFrame !== undefined) { t.onRenderFrame(); }
|
|
|
|
|
}, this.onRenderStop, this.onRenderStart);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -720,4 +730,6 @@
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
}).call(this);
|
|
|
|
|
|
|
|
|
|
return Springy;
|
|
|
|
|
}));
|
|
|
|
|