sigma
Version:
A JavaScript library dedicated to graph drawing.
85 lines (65 loc) • 1.95 kB
text/typescript
/**
* Sigma.js Animation Helpers
* ===========================
*
* Handy helper functions dealing with nodes & edges attributes animation.
* @module
*/
import Graph from "graphology";
import { PlainObject } from "../types";
import { cancelFrame, requestFrame } from "./index";
import easings from "./easings";
/**
* Defaults.
*/
export interface AnimateOptions {
easing: keyof typeof easings | ((k: number) => number);
duration: number;
}
export const ANIMATE_DEFAULTS = {
easing: "quadraticInOut",
duration: 150,
};
/**
* Function used to animate the nodes.
*/
export function animateNodes(
graph: Graph,
targets: PlainObject<PlainObject<number>>,
opts: Partial<AnimateOptions>,
callback: () => void,
): () => void {
const options: AnimateOptions = Object.assign({}, ANIMATE_DEFAULTS, opts);
const easing: (k: number) => number = typeof options.easing === "function" ? options.easing : easings[options.easing];
const start = Date.now();
const startPositions: PlainObject<PlainObject<number>> = {};
for (const node in targets) {
const attrs = targets[node];
startPositions[node] = {};
for (const k in attrs) startPositions[node][k] = graph.getNodeAttribute(node, k);
}
let frame: number | null = null;
const step = () => {
let p = (Date.now() - start) / options.duration;
if (p >= 1) {
// Animation is done
for (const node in targets) {
const attrs = targets[node];
for (const k in attrs) graph.setNodeAttribute(node, k, attrs[k]);
}
if (typeof callback === "function") callback();
return;
}
p = easing(p);
for (const node in targets) {
const attrs = targets[node];
const s = startPositions[node];
for (const k in attrs) graph.setNodeAttribute(node, k, attrs[k] * p + s[k] * (1 - p));
}
frame = requestFrame(step);
};
step();
return () => {
if (frame) cancelFrame(frame);
};
}