World-space rendering: geometry cached once, zoom pays only rasterization
Fixes the zoom frame-rate collapse and rebuilds draw() around a single camera transform, per the user's Obsidian-style sizing proposal. Bug fix first: the eased zoom leaked a queued rAF callback per frame -- advanceZoom applies each step through d3-zoom, whose zoom event called markDirty() from inside the tick loop, scheduling an extra draw while the loop scheduled its own. Draws multiplied per displayed frame; sustained wheel ran at ~20fps against a 120Hz display. markDirty now skips scheduling while inTick (verified: 62 frames/500ms during a 28x zoom burst, matching pan). World-space model: every draw call now runs in graph coordinates under one setTransform(k). Sizes are defined as screen-px-at-fit and converted once per geometry build (/ kFit), so nodes, node labels, arrowheads and the hover halo scale with the graph as you zoom (0.25x painted area at half zoom, exactly k^2) while edge widths and hull borders stay viewer-relative hairlines (/ k). Cluster hull geometry (convex hull + three offset fills + solid boundary -- dashes dropped for now) is built as cached Path2Ds per data/visibility/settings change; camera moves do zero geometry math, making zoom per-frame cost identical to pan. Label wrapping runs once per build, not per frame. Region labels stay viewer-relative (18px at any zoom) as UI chrome. Picking radius scales with the world-sized discs. Glide feel: ZOOM_EASE_MS 120 -> 45, convergence 0.1% -> 0.2%; a notch now settles in ~260ms instead of ~750ms. Resize still paints synchronously. Also fixes barrel-law lint violations from the settings wave (import from @/src/core and @/src/server, not deep module paths).
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
|
||||
export * from "./contracts.ts";
|
||||
export * from "./ports.ts";
|
||||
export * from "./render-settings.ts";
|
||||
|
||||
export * from "./question-core.ts";
|
||||
export * from "./clusters.ts";
|
||||
|
||||
Reference in New Issue
Block a user