rewritten using elkjs
This commit is contained in:
+37
-66
@@ -1,8 +1,10 @@
|
||||
import createGraph, { Graph } from "ngraph.graph";
|
||||
import createLayout from "ngraph.forcelayout";
|
||||
import ELK, { ElkNode } from "elkjs/lib/elk.bundled.js";
|
||||
import { Node } from "../types";
|
||||
|
||||
const ITERATION_COUNT = 10;
|
||||
const elk = new ELK();
|
||||
|
||||
const NODE_WIDTH = 100;
|
||||
const NODE_HEIGHT = 90;
|
||||
|
||||
export type Node2D = {
|
||||
id: Node['id'];
|
||||
@@ -10,70 +12,39 @@ export type Node2D = {
|
||||
node: Node;
|
||||
}
|
||||
|
||||
export function build2dNodes(nodes: Node[], area: { width: number, height: number, padding: number }): Node2D[] {
|
||||
const graph = createGraph();
|
||||
for (const node of nodes) {
|
||||
graph.addNode(node.behaviour.id, { node });
|
||||
}
|
||||
for (const node of nodes) {
|
||||
for (const link of node.behaviour.getDisplayInfo().links)
|
||||
graph.addLink(node.behaviour.id, link.target);
|
||||
}
|
||||
return buildGraph2dNodes(graph, area);
|
||||
}
|
||||
export async function build2dNodes(nodes: Node[], area: { width: number, height: number, padding: number }): Promise<Node2D[]> {
|
||||
const nodesById = new Map(nodes.map((node) => [node.behaviour.id, node]));
|
||||
|
||||
function buildGraph2dNodes(graph: Graph, area: { width: number, height: number, padding: number }): Node2D[] {
|
||||
const layout = createLayout(
|
||||
graph,
|
||||
{
|
||||
springLength: 300,
|
||||
// springTransform: (link, spring) => {
|
||||
// const from = graph.getNode(link.fromId).data.radius;
|
||||
// const to = graph.getNode(link.toId).data.radius;
|
||||
// spring.length = from + to + 10; // отступ 10px
|
||||
// },
|
||||
const graph: ElkNode = {
|
||||
id: "root",
|
||||
layoutOptions: {
|
||||
"elk.algorithm": "layered",
|
||||
"elk.direction": "RIGHT",
|
||||
"elk.spacing.nodeNode": "60",
|
||||
"elk.layered.spacing.nodeNodeBetweenLayers": "100",
|
||||
},
|
||||
);
|
||||
children: nodes.map((node) => ({
|
||||
id: node.behaviour.id,
|
||||
width: NODE_WIDTH,
|
||||
height: NODE_HEIGHT,
|
||||
})),
|
||||
edges: nodes.flatMap((node) =>
|
||||
node.behaviour.getDisplayInfo().links.map((link, idx) => ({
|
||||
id: `${node.behaviour.id}->${link.target}.${idx}`,
|
||||
sources: [node.behaviour.id],
|
||||
targets: [link.target],
|
||||
}))
|
||||
),
|
||||
};
|
||||
|
||||
function clampToBounds() {
|
||||
const minX = area.padding;
|
||||
const maxX = area.width - area.padding;
|
||||
const minY = area.padding;
|
||||
const maxY = area.height - area.padding;
|
||||
layout.forEachBody((body) => {
|
||||
if (body.pos.x < minX) { body.pos.x = minX; body.velocity.x = 0; }
|
||||
if (body.pos.x > maxX) { body.pos.x = maxX; body.velocity.x = 0; }
|
||||
if (body.pos.y < minY) { body.pos.y = minY; body.velocity.y = 0; }
|
||||
if (body.pos.y > maxY) { body.pos.y = maxY; body.velocity.y = 0; }
|
||||
});
|
||||
}
|
||||
const layout = await elk.layout(graph);
|
||||
|
||||
for (var i = 0; i < ITERATION_COUNT; ++i) {
|
||||
layout.step();
|
||||
// clampToBounds();
|
||||
}
|
||||
|
||||
// const rect = layout.getGraphRect();
|
||||
// const W = area.width, H = 600, PADDING = 40;
|
||||
|
||||
// const scaleX = (area.width - area.padding * 2) / (rect.x2 - rect.x1);
|
||||
// const scaleY = (area.height - area.padding * 2) / (rect.y2 - rect.y1);
|
||||
// const scale = Math.min(scaleX, scaleY); // сохраняем пропорции
|
||||
|
||||
// function toCanvas(pos: { x: number; y: number }) {
|
||||
// return {
|
||||
// x: area.padding + (pos.x - rect.x1) * scale,
|
||||
// y: area.padding + (pos.y - rect.y1) * scale,
|
||||
// };
|
||||
// }
|
||||
|
||||
const nodes: Node2D[] = [];
|
||||
layout.forEachBody((body, nodeId) => {
|
||||
nodes.push({
|
||||
id: nodeId.toString(),
|
||||
position: { x: body.pos.x + area.width / 2, y: body.pos.y + area.height / 2 },
|
||||
node: graph.getNode(nodeId)?.data.node,
|
||||
});
|
||||
});
|
||||
return nodes;
|
||||
}
|
||||
return (layout.children ?? []).map((child) => ({
|
||||
id: child.id,
|
||||
position: {
|
||||
x: (child.x ?? 0) + area.padding,
|
||||
y: (child.y ?? 0) + area.padding,
|
||||
},
|
||||
node: nodesById.get(child.id)!,
|
||||
}));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user