Compare commits

..

25 Commits

Author SHA1 Message Date
Dennis Hotson
9654b64f85
Merge pull request #98 from iangilman/render
Changed onRender to onRenderFrame
2018-03-06 11:32:22 +11:00
Ian Gilman
8beaeff267 Changed onRender to onRenderFrame 2018-03-05 16:25:05 -08:00
Dennis Hotson
73ecbc773c
Merge pull request #97 from iangilman/render
Added onRender callback for after each frame
2018-03-01 23:54:53 +11:00
Ian Gilman
73fd49c58a Added onRender callback for after each frame 2018-02-28 16:33:23 -08:00
Dennis Hotson
6158298c9e Merge pull request #85 from mwcz/max-speed
add maxSpeed parameter to Layout.ForceDirected constructor
2016-12-29 10:22:56 +11:00
mwcz
e490969ea0 add maxSpeed parameter to Layout.ForceDirected constructor 2016-07-19 14:38:01 -04:00
Dennis Hotson
559a400331 Merge pull request #70 from shigeruNakajima/node_color
Add nodes a 'color' property.
2014-12-08 10:52:18 +11:00
Dennis Hotson
921b3e83e5 Fix whitespace 2014-12-08 10:39:11 +11:00
Dennis Hotson
6f99308b44 Small fix to UMD wrapper 2014-12-08 10:38:19 +11:00
Dennis Hotson
fd785d8b10 Version bump 2014-12-08 10:31:05 +11:00
Dennis Hotson
6716fab883 Universal module pattern (for browserify support) 2014-12-08 10:29:31 +11:00
shigeru.nakajima
322a7bae8b Add node color. 2014-10-10 18:48:27 +09:00
Dennis Hotson
4480a8e3ff Bump to 2.6.1 2014-07-30 21:37:13 +10:00
Dennis Hotson
c41ff98d3c Bump version to 2.6.0 2014-07-27 12:18:58 +10:00
Dennis Hotson
d3c3be9325 Merge pull request #67 from lgvalent/patch-1
Update springyui.js
2014-07-24 21:55:15 +10:00
Lucio Valentin
487afff1b2 Update springyui.js
A simple error at end of line 35.
2014-07-22 16:58:16 -03:00
Dennis Hotson
db74df106c Merge pull request #65 from Irrational86/master
Fixed order of 'onRenderStop' and 'onRenderStart' parameters when calling this.layout.start()
2014-07-18 11:33:30 +10:00
Dennis Hotson
c14da4feae Merge pull request #66 from Irrational86/springyui-minEnergyThreshold
Enabled the ability to specify the parameter 'minEnergyThreshold' in springyui.js
2014-07-18 11:32:31 +10:00
Jesse
f51be2fc48 Enabled the ability to specify the parameter 'minEnergyThreshold' in springyui.js.
Also made the default value in springyui be very small, in order to cause the animation to end/stop smoothly.
2014-07-12 17:32:02 -04:00
Jesse
b3145ce522 Fixed order of 'onRenderStop' and 'onRenderStop' parameters when calling this.layout.start(). 2014-07-12 14:18:05 -04:00
Dennis Hotson
0a588deed6 Bumped version to 2.5.0 2014-06-01 18:31:09 +10:00
Dennis Hotson
441ccfcc2b Added tick for manually stepping through simulation 2014-06-01 18:29:54 +10:00
Dennis Hotson
f64bda19bc Bumped verison to 2.4.0 2014-06-01 18:25:44 +10:00
Dennis Hotson
1d51239af1 Merge pull request #63 from WebOnWebOff/master
Allow configuration of minimum energy threshold
2014-06-01 18:17:33 +10:00
'WebOnWebOff'
50eed3e039 Allow configuration of minimum energy threshold 2014-05-20 17:18:00 +03:00
4 changed files with 55 additions and 37 deletions

View File

@ -1,7 +1,7 @@
{ {
"name": "Springy", "name": "Springy",
"main": "springy.js", "main": "springy.js",
"version": "2.3.0", "version": "2.7.1",
"homepage": "https://github.com/dhotson/springy", "homepage": "https://github.com/dhotson/springy",
"authors": [ "authors": [
"Dennis Hotson <dennis@99designs.com>" "Dennis Hotson <dennis@99designs.com>"

View File

@ -1,6 +1,6 @@
{ {
"name": "springy", "name": "springy",
"version": "2.3.0", "version": "2.7.1",
"description": "A force directed graph layout algorithm in JavaScript.", "description": "A force directed graph layout algorithm in JavaScript.",
"main": "springy.js", "main": "springy.js",
"scripts": { "scripts": {

View File

@ -1,5 +1,5 @@
/** /**
* Springy v2.3.0 * Springy v2.7.1
* *
* Copyright (c) 2010-2013 Dennis Hotson * Copyright (c) 2010-2013 Dennis Hotson
* *
@ -24,22 +24,24 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE. * OTHER DEALINGS IN THE SOFTWARE.
*/ */
(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 {
// Browser globals
root.Springy = factory();
}
}(this, function() {
(function() { var Springy = {};
// 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;
} else {
Springy = root.Springy = {};
}
var Graph = Springy.Graph = function() { var Graph = Springy.Graph = function() {
this.nodeSet = {}; this.nodeSet = {};
@ -325,11 +327,13 @@
// ----------- // -----------
var Layout = Springy.Layout = {}; var Layout = Springy.Layout = {};
Layout.ForceDirected = function(graph, stiffness, repulsion, damping) { Layout.ForceDirected = function(graph, stiffness, repulsion, damping, minEnergyThreshold, maxSpeed) {
this.graph = graph; this.graph = graph;
this.stiffness = stiffness; // spring stiffness constant this.stiffness = stiffness; // spring stiffness constant
this.repulsion = repulsion; // repulsion constant this.repulsion = repulsion; // repulsion constant
this.damping = damping; // velocity damping factor 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.nodePoints = {}; // keep track of points associated with nodes
this.edgeSprings = {}; // keep track of springs associated with edges this.edgeSprings = {}; // keep track of springs associated with edges
@ -448,6 +452,9 @@
// Is this, along with updatePosition below, the only places that your // Is this, along with updatePosition below, the only places that your
// integration code exist? // integration code exist?
point.v = point.v.add(point.a.multiply(timestep)).multiply(this.damping); 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); point.a = new Vector(0,0);
}); });
}; };
@ -473,14 +480,14 @@
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; // stolen from coffeescript, thanks jashkenas! ;-) var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; // stolen from coffeescript, thanks jashkenas! ;-)
Springy.requestAnimationFrame = __bind(root.requestAnimationFrame || Springy.requestAnimationFrame = __bind(this.requestAnimationFrame ||
root.webkitRequestAnimationFrame || this.webkitRequestAnimationFrame ||
root.mozRequestAnimationFrame || this.mozRequestAnimationFrame ||
root.oRequestAnimationFrame || this.oRequestAnimationFrame ||
root.msRequestAnimationFrame || this.msRequestAnimationFrame ||
(function(callback, element) { (function(callback, element) {
root.setTimeout(callback, 10); this.setTimeout(callback, 10);
}), root); }), this);
/** /**
@ -497,18 +504,14 @@
if (onRenderStart !== undefined) { onRenderStart(); } if (onRenderStart !== undefined) { onRenderStart(); }
Springy.requestAnimationFrame(function step() { Springy.requestAnimationFrame(function step() {
t.applyCoulombsLaw(); t.tick(0.03);
t.applyHookesLaw();
t.attractToCentre();
t.updateVelocity(0.03);
t.updatePosition(0.03);
if (render !== undefined) { if (render !== undefined) {
render(); render();
} }
// stop simulation when energy of the system goes below a threshold // stop simulation when energy of the system goes below a threshold
if (t._stop || t.totalEnergy() < 0.01) { if (t._stop || t.totalEnergy() < t.minEnergyThreshold) {
t._started = false; t._started = false;
if (onRenderStop !== undefined) { onRenderStop(); } if (onRenderStop !== undefined) { onRenderStop(); }
} else { } else {
@ -521,6 +524,14 @@
this._stop = true; this._stop = true;
} }
Layout.ForceDirected.prototype.tick = function(timestep) {
this.applyCoulombsLaw();
this.applyHookesLaw();
this.attractToCentre();
this.updateVelocity(timestep);
this.updatePosition(timestep);
};
// Find the nearest point to a particular position // Find the nearest point to a particular position
Layout.ForceDirected.prototype.nearest = function(pos) { Layout.ForceDirected.prototype.nearest = function(pos) {
var min = {node: null, point: null, distance: null}; var min = {node: null, point: null, distance: null};
@ -634,14 +645,16 @@
* Renderer handles the layout rendering loop * Renderer handles the layout rendering loop
* @param onRenderStop optional callback function that gets executed whenever rendering stops. * @param onRenderStop optional callback function that gets executed whenever rendering stops.
* @param onRenderStart optional callback function that gets executed whenever rendering starts. * @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.layout = layout;
this.clear = clear; this.clear = clear;
this.drawEdge = drawEdge; this.drawEdge = drawEdge;
this.drawNode = drawNode; this.drawNode = drawNode;
this.onRenderStop = onRenderStop; this.onRenderStop = onRenderStop;
this.onRenderStart = onRenderStart; this.onRenderStart = onRenderStart;
this.onRenderFrame = onRenderFrame;
this.layout.graph.addGraphListener(this); this.layout.graph.addGraphListener(this);
} }
@ -672,7 +685,9 @@
t.layout.eachNode(function(node, point) { t.layout.eachNode(function(node, point) {
t.drawNode(node, point.p); t.drawNode(node, point.p);
}); });
}, this.onRenderStart, this.onRenderStop);
if (t.onRenderFrame !== undefined) { t.onRenderFrame(); }
}, this.onRenderStop, this.onRenderStart);
}; };
Renderer.prototype.stop = function() { Renderer.prototype.stop = function() {
@ -715,4 +730,6 @@
} }
return true; return true;
}; };
}).call(this);
return Springy;
}));

View File

@ -32,6 +32,7 @@ jQuery.fn.springy = function(params) {
var stiffness = params.stiffness || 400.0; var stiffness = params.stiffness || 400.0;
var repulsion = params.repulsion || 400.0; var repulsion = params.repulsion || 400.0;
var damping = params.damping || 0.5; var damping = params.damping || 0.5;
var minEnergyThreshold = params.minEnergyThreshold || 0.00001;
var nodeSelected = params.nodeSelected || null; var nodeSelected = params.nodeSelected || null;
var nodeImages = {}; var nodeImages = {};
var edgeLabelsUpright = true; var edgeLabelsUpright = true;
@ -39,7 +40,7 @@ jQuery.fn.springy = function(params) {
var canvas = this[0]; var canvas = this[0];
var ctx = canvas.getContext("2d"); var ctx = canvas.getContext("2d");
var layout = this.layout = new Springy.Layout.ForceDirected(graph, stiffness, repulsion, damping); var layout = this.layout = new Springy.Layout.ForceDirected(graph, stiffness, repulsion, damping, minEnergyThreshold);
// calculate bounding box of graph layout.. with ease-in // calculate bounding box of graph layout.. with ease-in
var currentBB = layout.getBoundingBox(); var currentBB = layout.getBoundingBox();
@ -323,7 +324,7 @@ jQuery.fn.springy = function(params) {
ctx.textAlign = "left"; ctx.textAlign = "left";
ctx.textBaseline = "top"; ctx.textBaseline = "top";
ctx.font = (node.data.font !== undefined) ? node.data.font : nodeFont; ctx.font = (node.data.font !== undefined) ? node.data.font : nodeFont;
ctx.fillStyle = "#000000"; ctx.fillStyle = (node.data.color !== undefined) ? node.data.color : "#000000";
var text = (node.data.label !== undefined) ? node.data.label : node.id; var text = (node.data.label !== undefined) ? node.data.label : node.id;
ctx.fillText(text, s.x - contentWidth/2, s.y - contentHeight/2); ctx.fillText(text, s.x - contentWidth/2, s.y - contentHeight/2);
} else { } else {