function pathForce(path, nodes, {
strength = .1,
offset = (n, i, nodes) => i / nodes.length,
initialize = true,
clamp = Infinity
} = {}) {
const getStrength = callable(strength),
getClamp = callable(clamp),
getScale = max => !isFinite(max) ? () => 1 : (dx, dy) => {
const d = Math.hypot(dx, dy);
return d ? Math.min(max, d) / d : 0;
},
getPoint = (i, l) => path.getPointAtLength(offset(nodes[i], i, nodes) * l),
getLength = () => path.getTotalLength();
if(initialize) {
const l = getLength();
for(let i = 0, p; i < nodes.length; i++) {
p = getPoint(i, l);
nodes[i].x = p.x;
nodes[i].y = p.y;
}
}
return () => {
const l = getLength(),
s = getStrength(),
clamp = getScale(getClamp());
for(let i = 0, p, n, dx, dy, c; i < nodes.length; i++) {
p = getPoint(i, l);
n = nodes[i];
dx = s * (p.x - n.x);
dy = s * (p.y - n.y);
c = clamp(dx, dy);
n.vx += c * dx;
n.vy += c * dy;
}
};
};