b9e42c3ef4
Build and Deploy / build-and-deploy (push) Has been cancelled
- lit-force-graph: Refactored for instance reuse, better lifecycle management, and added dynamic imports for AR/VR modes. - lit-html-table: Improved visual design, readability of headers, and fixed reactivity in editable mode. - lit-draggable-dom: Fixed clipping issues by switching to relative/absolute positioning and resolved a panning speed bug caused by CSS variable inheritance.
67 lines
2.2 KiB
TypeScript
67 lines
2.2 KiB
TypeScript
import ForceGraph from "force-graph";
|
|
import { RenderContext } from "../classes/context";
|
|
|
|
export function render(context: RenderContext) {
|
|
const graph = context.instance || ForceGraph();
|
|
const style = getComputedStyle(context.element);
|
|
const lineColor = style.getPropertyValue("--graph-line-color").trim() || "#555";
|
|
const bgColor = style.getPropertyValue("--graph-background-color").trim() || "#000011";
|
|
const fgColor = style.getPropertyValue("--graph-foreground-color").trim() || "#ffffff";
|
|
const nodeColor = style.getPropertyValue("--graph-node-color").trim() || "#999";
|
|
const width = context.element.clientWidth || Number(style.width.slice(0, -2)) || window.innerWidth;
|
|
const height = context.element.clientHeight || Number(style.height.slice(0, -2)) || window.innerHeight;
|
|
|
|
if (!context.instance) {
|
|
graph(context.element);
|
|
}
|
|
|
|
graph
|
|
.graphData(context.data)
|
|
.width(width)
|
|
.height(height)
|
|
.cooldownTicks(100)
|
|
.backgroundColor(bgColor)
|
|
.linkColor(() => lineColor)
|
|
.linkWidth(0.2)
|
|
.nodeCanvasObject((node: any, ctx, globalScale) => {
|
|
// Draw a circle
|
|
ctx.beginPath();
|
|
const size = 5 / globalScale;
|
|
ctx.arc(node.x, node.y, size, 0, 2 * Math.PI);
|
|
ctx.fillStyle = nodeColor;
|
|
ctx.fill();
|
|
ctx.lineWidth = 1 / globalScale;
|
|
ctx.strokeStyle = lineColor;
|
|
ctx.stroke();
|
|
|
|
if (globalScale >= 4) {
|
|
const label = node.name ?? node.id;
|
|
const fontSize = 12 / globalScale;
|
|
ctx.font = `${fontSize}px Sans-Serif`;
|
|
const textWidth = ctx.measureText(label).width;
|
|
const bckgDimensions = [textWidth, fontSize].map(
|
|
(n) => n + fontSize * 0.2
|
|
); // some padding
|
|
|
|
ctx.textAlign = "center";
|
|
ctx.textBaseline = "middle";
|
|
ctx.fillStyle = fgColor;
|
|
// Measure text
|
|
ctx.fillText(label, node.x + size * 2 + textWidth / 2, node.y);
|
|
|
|
node.__bckgDimensions = bckgDimensions;
|
|
}
|
|
})
|
|
.onNodeHover((node: any, prev: any) => {
|
|
if (node) {
|
|
const graphNode = context.data.nodes.find((n) => n.id === node.id);
|
|
context.onHover(graphNode);
|
|
}
|
|
if (prev) {
|
|
context.onHover(undefined);
|
|
}
|
|
});
|
|
|
|
return graph;
|
|
}
|