perf(web/mazenet): ref-driven pan, memoized children, indexed edge lookup

Pan/zoom previously drove a full Canvas re-render on every mousemove
via setPan() — at 30 LANs that's ~1000 SVG paths and div cards
re-evaluating 60 times a second while you drag. The browser screamed.

Three fixes, one surgical pass:

1. Pan drag writes the translate/scale transform directly to the
   pan-layer DOM ref inside requestAnimationFrame; setPan is deferred
   to mouseup. Grid pattern attributes (x/y/width/height) get the
   same treatment so the backdrop stays glued to the canvas content.
   Wheel zoom, resetPan, and zoomBy also sync refs + fire a write so
   React-driven changes land in one frame.

2. Edge rendering swaps the nodes.find() inside .map() for a
   Map<id, node> built once per render — O(E) instead of O(E·N).
   NetBox + NodeCard are now wrapped in React.memo; Canvas hoists
   the setSelection closures into useCallback so memo can actually
   short-circuit instead of seeing a fresh prop every render.

3. Drag-a-single-node still mutates state and re-renders, but now
   only the moved node rerenders — the other 89 skip via memo.

Everything that reads panRef.current (toWorld, context menu, drop
targeting) still sees the live value during drag because we mutate
the ref synchronously on each mousemove; only React state is lazy.
This commit is contained in:
2026-04-24 18:48:05 -04:00
parent c973ded2fc
commit 207f791684
5 changed files with 92 additions and 14 deletions

View File

@@ -79,4 +79,4 @@ const NetBox: React.FC<Props> = ({
);
};
export default NetBox;
export default React.memo(NetBox);