[TASK] Add animation & improve behaviour of forcegraph

This commit is contained in:
Martin Geno 2017-04-14 20:43:03 +02:00 committed by Xaver Maierhofer
parent 0987b4b39a
commit 3e63b6432e
No known key found for this signature in database
GPG Key ID: 7FDCE23FD2EC9FE8

View File

@ -1,5 +1,5 @@
define(['d3-selection', 'd3-force', 'd3-zoom', 'd3-drag', 'utils/math', 'forcegraph/draw'], define(['d3-selection', 'd3-force', 'd3-zoom', 'd3-drag', 'd3-timer', 'd3-ease', 'd3-interpolate', 'utils/math', 'forcegraph/draw'],
function (d3Selection, d3Force, d3Zoom, d3Drag, math, draw) { function (d3Selection, d3Force, d3Zoom, d3Drag, d3Timer, d3Ease, d3Interpolate, math, draw) {
'use strict'; 'use strict';
return function (config, linkScale, sidebar, router) { return function (config, linkScale, sidebar, router) {
@ -14,10 +14,12 @@ define(['d3-selection', 'd3-force', 'd3-zoom', 'd3-drag', 'utils/math', 'forcegr
var intNodes = []; var intNodes = [];
var dictNodes = {}; var dictNodes = {};
var intLinks = []; var intLinks = [];
var movetoTimer;
var NODE_RADIUS_DRAG = 10; var NODE_RADIUS_DRAG = 10;
var NODE_RADIUS_SELECT = 15; var NODE_RADIUS_SELECT = 15;
var LINK_RADIUS_SELECT = 12; var LINK_RADIUS_SELECT = 12;
var ZOOM_ANIMATE_DURATION = 350;
var ZOOM_MIN = 1 / 8; var ZOOM_MIN = 1 / 8;
var ZOOM_MAX = 3; var ZOOM_MAX = 3;
@ -32,9 +34,43 @@ define(['d3-selection', 'd3-force', 'd3-zoom', 'd3-drag', 'utils/math', 'forcegr
draw.setMaxArea(canvas.width, canvas.height); draw.setMaxArea(canvas.width, canvas.height);
} }
function moveTo(x, y) { function transformPosition(p) {
transform.x = (canvas.width + sidebar()) / 2 - x * transform.k; transform.x = p.x;
transform.y = canvas.height / 2 - y * transform.k; transform.y = p.y;
transform.k = p.k;
}
function moveTo(callback, forceMove) {
clearTimeout(movetoTimer);
if (!forceMove && force.alpha() > 0.3) {
movetoTimer = setTimeout(function timerOfMoveTo() {
moveTo(callback);
}, 300);
return;
}
var result = callback();
var x = result[0];
var y = result[1];
var k = result[2];
var end = { k: k };
end.x = (canvas.width + sidebar()) / 2 - x * k;
end.y = canvas.height / 2 - y * k;
var start = { x: transform.x, y: transform.y, k: transform.k };
var interpolate = d3Interpolate.interpolateObject(start, end);
var timer = d3Timer.timer(function (t) {
if (t >= ZOOM_ANIMATE_DURATION) {
timer.stop();
return;
}
var v = interpolate(d3Ease.easeQuadInOut(t / ZOOM_ANIMATE_DURATION));
transformPosition(v);
window.requestAnimationFrame(redraw);
});
} }
function onClick() { function onClick() {
@ -111,7 +147,8 @@ define(['d3-selection', 'd3-force', 'd3-zoom', 'd3-drag', 'utils/math', 'forcegr
.force('x', d3Force.forceX().strength(0.02)) .force('x', d3Force.forceX().strength(0.02))
.force('y', d3Force.forceY().strength(0.02)) .force('y', d3Force.forceY().strength(0.02))
.force('collide', d3Force.forceCollide()) .force('collide', d3Force.forceCollide())
.on('tick', redraw); .on('tick', redraw)
.alphaDecay(0.015);
var drag = d3Drag.drag() var drag = d3Drag.drag()
.subject(function () { .subject(function () {
@ -192,40 +229,40 @@ define(['d3-selection', 'd3-force', 'd3-zoom', 'd3-drag', 'utils/math', 'forcegr
}; };
self.resetView = function resetView() { self.resetView = function resetView() {
draw.setHighlight(null); moveTo(function calcToReset() {
transform.k = (ZOOM_MIN + 1) / 2; draw.setHighlight(null);
moveTo(0, 0); return [0, 0, (ZOOM_MIN + 1) / 2];
redraw(); }, true);
}; };
self.gotoNode = function gotoNode(d) { self.gotoNode = function gotoNode(d) {
for (var i = 0; i < intNodes.length; i++) { moveTo(function calcToNode() {
var n = intNodes[i]; for (var i = 0; i < intNodes.length; i++) {
if (n.o.node.nodeinfo.node_id !== d.nodeinfo.node_id) { var n = intNodes[i];
continue; if (n.o.node.nodeinfo.node_id !== d.nodeinfo.node_id) {
continue;
}
draw.setHighlight({ type: 'node', o: n.o.node });
return [n.x, n.y, (ZOOM_MAX + 1) / 2];
} }
draw.setHighlight({ type: 'node', o: n.o.node }); return [0, 0, (ZOOM_MIN + 1) / 2];
transform.k = (ZOOM_MAX + 1) / 2; });
moveTo(n.x, n.y);
break;
}
redraw();
}; };
self.gotoLink = function gotoLink(d) { self.gotoLink = function gotoLink(d) {
draw.setHighlight({ type: 'link', o: d }); moveTo(function calcToLink() {
for (var i = 0; i < intLinks.length; i++) { draw.setHighlight({ type: 'link', o: d });
var l = intLinks[i]; for (var i = 0; i < intLinks.length; i++) {
if (l.o !== d) { var l = intLinks[i];
continue; if (l.o !== d) {
continue;
}
return [(l.source.x + l.target.x) / 2, (l.source.y + l.target.y) / 2, (ZOOM_MAX / 2) + ZOOM_MIN];
} }
moveTo((l.source.x + l.target.x) / 2, (l.source.y + l.target.y) / 2); return [0, 0, (ZOOM_MIN + 1) / 2];
break; });
}
redraw();
}; };
self.gotoLocation = function gotoLocation() { self.gotoLocation = function gotoLocation() {
// ignore // ignore
}; };