d3-force-elastic
Version:
A Hooke's law spring-like attraction force between node pairs for the d3-force simulation engine.
114 lines (102 loc) • 4.05 kB
JavaScript
// Version 1.0.0 d3-force-elastic - https://github.com/vasturiano/d3-force-elastic
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.d3 = global.d3 || {}));
})(this, (function (exports) { 'use strict';
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
function constant (x) {
return function () {
return x;
};
}
function elastic () {
var links = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var nDim,
nodes = [],
id = function id(node) {
return node.index;
},
// accessor: node unique id
distance = function distance(link) {
return 30;
},
// accessor: number
elasticity = function elasticity(link) {
return 0.8;
}; // accessor: number between 0 and 1
function force(alpha) {
for (var i = 0; i < links.length; i++) {
var link = links[i],
dx = link.target.x - link.source.x,
dy = link.target.y - link.source.y || 0,
dz = link.target.z - link.source.z || 0,
d = calcDist(dx, dy, dz);
var linkLen = distance(link);
if (d <= linkLen) continue; // Elastic not extended, no effect
var strength = alpha * elasticity(link) * (d - linkLen);
// Move only one side if opposite node is fixed
var bias = link.source.fx != null ? 0 : link.target.fx != null ? 1 : 0.5;
var srcAcceleration = strength * bias;
var tgtAcceleration = strength * (1 - bias);
link.source.vx += dx / d * srcAcceleration;
link.target.vx -= dx / d * tgtAcceleration;
if (nDim > 1) {
link.source.vy += dy / d * srcAcceleration;
link.target.vy -= dy / d * tgtAcceleration;
}
if (nDim > 2) {
link.source.vz += dz / d * srcAcceleration;
link.target.vz -= dz / d * tgtAcceleration;
}
}
}
function initialize() {
var nodesById = new Map(nodes.map(function (d, i) {
return [id(d, i, nodes), d];
}));
links.forEach(function (link) {
if (_typeof(link.source) !== "object") link.source = nodesById.get(link.source) || link.source;
if (_typeof(link.target) !== "object") link.target = nodesById.get(link.target) || link.target;
});
}
force.initialize = function (initNodes) {
nodes = initNodes;
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
nDim = args.find(function (arg) {
return [1, 2, 3].includes(arg);
}) || 2;
initialize();
};
force.links = function (_) {
return arguments.length ? (links = _, initialize(), force) : links;
};
force.id = function (_) {
return arguments.length ? (id = _, force) : id;
};
force.distance = function (_) {
return arguments.length ? (distance = typeof _ === 'function' ? _ : constant(+_), force) : distance;
};
force.elasticity = function (_) {
return arguments.length ? (elasticity = typeof _ === 'function' ? _ : constant(+_), force) : elasticity;
};
return force;
}
//
function calcDist(x) {
var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var z = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
return Math.sqrt(x * x + y * y + z * z);
}
exports.forceElastic = elastic;
}));
//# sourceMappingURL=d3-force-elastic.js.map