Renderer swap: drop sigma.js for a hand-rolled single-canvas 2D renderer
Implements Option B from docs/research/graph-rendering.md. sigma.js v3 (WebGL) is replaced by one canvas, one rAF loop with a dirty flag, and d3-zoom for the camera — eliminating the entire bug class from the sigma-era bolt-on architecture: - Hull/node desync during pan (two independent render loops) is now structurally impossible: hull fills, dashed hull strokes, edges with arrowheads, node discs, region labels, node labels, and hover glow are all drawn in ONE frame under ONE camera. - The settings-change canvas-sizing race (everything shifting up-left) is gone: settings changes only redraw; the canvas and camera persist (verified live: camera identical to 15 decimals across a slider drag). - The GPU floor is gone: idle schedules NO frames at all (verified via pixel-identity over 600ms idle); pan redraws exactly once per frame. components/graph-canvas.ts: GraphCanvasRenderer class plus pure helpers (zoomRatioOf, labelAlpha, fitTransform, arrowGeometry, pickNearest). The sigma camera-ratio convention (1 = fit, smaller = zoomed in) is kept verbatim so persisted labelZoom settings survive the swap; node labels and cluster region labels cross-fade over the same LABELS_FADE_SPAN (0.5, unchanged). Picking is a nearest-node distance check with the 10px pad that replaces the old padded-picking vertex shader. Hull math stays in components/cluster-geometry.ts, reused as-is. No ctx.filter, ever. graph-view.tsx keeps every feature: fetch/refetch on runs-empty, FA2 run-then-freeze layout, localStorage render settings + sanitizers, search filtering with edge drops and card-close, detail card with flipped anchoring and per-source provenance, settings panel, import button, pipeline status chips. Only the renderer plumbing changed. tests/graph-canvas.test.ts pins the pure math: ratio direction, label gate + inverse complement (alphas sum to 1), fit transform padding, arrowhead tip-on-disc-edge and symmetry, picking pad/ties/null cases. Live-verified end-to-end on the real 338-node graph (dev server port 3002): single canvas, paint at fit, hover cursor+glow+fade, click card open/anchored/close, stage click, search filter to zero with hint, label gate opens via slider and zoom, cluster-labels toggle, zoom-to- cursor 0.56px anchor drift, camera persistence across settings, zero idle repaints. sigma dependency removed from package.json; d3-zoom and d3-selection added. Note: the settings feed effect needed isEmpty in its deps — without it the renderer mounted with settings=null and every draw early-returned (blank canvas); caught live, not by typecheck.
This commit is contained in:
Generated
+2
-11
@@ -24,6 +24,8 @@
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "^1.1.1",
|
||||
"d3-selection": "^3.0.0",
|
||||
"d3-zoom": "^3.0.0",
|
||||
"embla-carousel-react": "^8.6.0",
|
||||
"graphology": "^0.26.0",
|
||||
"graphology-communities-louvain": "^2.0.2",
|
||||
@@ -43,7 +45,6 @@
|
||||
"react-dom": "^19.2.8",
|
||||
"react-jsx-parser": "^2.4.1",
|
||||
"remark-breaks": "^4.0.0",
|
||||
"sigma": "^3.0.3",
|
||||
"streamdown": "^2.5.0",
|
||||
"tailwind-merge": "^3.6.0",
|
||||
"tokenlens": "^1.3.1",
|
||||
@@ -13342,16 +13343,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/sigma": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sigma/-/sigma-3.0.3.tgz",
|
||||
"integrity": "sha512-5H0zFlx6/NTQpqBg4Rm569ZOpnBOXMaS25UQThIWMU3XyzI5AhmorK/gnl87BvJBLhQd0tW4C0LIp3enWzMoNw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"events": "^3.3.0",
|
||||
"graphology-utils": "^2.5.2"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||
|
||||
Reference in New Issue
Block a user