2016-04-06 04:50:36 +08:00
|
|
|
import {timer as newTimer} from "d3-timer";
|
|
|
|
|
import {dispatch as newDispatch} from "d3-dispatch";
|
|
|
|
|
|
|
|
|
|
export default function(nodes) {
|
2016-04-07 04:21:23 +08:00
|
|
|
var frame = 0,
|
|
|
|
|
frameMax = 300,
|
|
|
|
|
alphaDecay = -0.03,
|
|
|
|
|
velocityDecay = 0.9,
|
2016-04-06 04:50:36 +08:00
|
|
|
timer = newTimer(tick),
|
2016-04-07 04:21:23 +08:00
|
|
|
dispatch = newDispatch("start", "beforetick", "tick", "end");
|
2016-04-06 04:50:36 +08:00
|
|
|
|
2016-04-07 04:21:23 +08:00
|
|
|
function start() {
|
|
|
|
|
if (frame < Infinity) {
|
|
|
|
|
frame = 0;
|
|
|
|
|
dispatch.call("start", this);
|
|
|
|
|
timer.restart(tick);
|
2016-04-06 04:50:36 +08:00
|
|
|
} else {
|
2016-04-07 04:21:23 +08:00
|
|
|
frame = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function stop() {
|
|
|
|
|
if (frame < Infinity) {
|
|
|
|
|
frame = Infinity;
|
|
|
|
|
dispatch.call("end", this);
|
|
|
|
|
timer.stop();
|
2016-04-06 04:50:36 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function tick() {
|
2016-04-07 04:21:23 +08:00
|
|
|
if (++frame > frameMax) return stop();
|
2016-04-06 04:50:36 +08:00
|
|
|
|
2016-04-07 04:21:23 +08:00
|
|
|
dispatch.call("beforetick", this, Math.exp(frame * alphaDecay));
|
2016-04-06 04:50:36 +08:00
|
|
|
|
|
|
|
|
for (var i = 0, n = nodes.length, node; i < n; ++i) {
|
|
|
|
|
node = nodes[i];
|
2016-04-07 04:21:23 +08:00
|
|
|
node.x += node.vx *= velocityDecay;
|
|
|
|
|
node.y += node.vy *= velocityDecay;
|
2016-04-06 04:50:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dispatch.call("tick", this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
nodes: function(_) {
|
|
|
|
|
return arguments.length ? (nodes = _, this) : nodes;
|
|
|
|
|
},
|
|
|
|
|
start: function() {
|
2016-04-07 04:21:23 +08:00
|
|
|
return start(), this;
|
2016-04-06 04:50:36 +08:00
|
|
|
},
|
|
|
|
|
stop: function() {
|
2016-04-07 04:21:23 +08:00
|
|
|
return stop(), this;
|
2016-04-06 04:50:36 +08:00
|
|
|
},
|
2016-04-07 04:21:23 +08:00
|
|
|
frameMax: function(_) {
|
|
|
|
|
return arguments.length ? (frameMax = _, this) : frameMax;
|
2016-04-06 04:50:36 +08:00
|
|
|
},
|
|
|
|
|
alphaDecay: function(_) {
|
|
|
|
|
return arguments.length ? (alphaDecay = +_, this) : alphaDecay;
|
|
|
|
|
},
|
2016-04-07 04:21:23 +08:00
|
|
|
friction: function(_) {
|
|
|
|
|
return arguments.length ? (velocityDecay = 1 - _, this) : 1 - velocityDecay;
|
2016-04-06 04:50:36 +08:00
|
|
|
},
|
|
|
|
|
on: function(name, _) {
|
|
|
|
|
return arguments.length > 1 ? (dispatch.on(name, _), this) : dispatch.on(name);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|