Conversation
…abels fixed-size under zoom AxisLabels.ts held mutable module-global camera-baseline state that was shared across every CanvasD3 instance, breaking split view (fixes #492). Baseline is now per-canvas $state passed explicitly into the now-pure AxisLabels functions; getYabelY is renamed to getYLabelY. The base-scale constant (15/30, half/whole of GRID_SIZE_2D) is now a single named export instead of being duplicated as a bare literal in four places. Also fixes #478: axis-label text only compensated for the static initial zoom, so it grew/shrank as the user interactively zoomed. Latex2D gains an opt-in fixedScreenScale prop (used only by axis labels) that divides the label's scale by the live zoom factor exposed via a new 'current-zoom-k' context.
✅ Deploy Preview for openla-preview ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Screenshot diff report263 applets changed visually vs
Before/after/diff images are attached as the |
…legate live-zoom to Projection2D - getXLabelX/getYLabelY now take a single AxisLabelLayout object instead of 6-7 positional params that always travelled together (Data Clumps), and share a normalizeAxisLabelLayout() preamble instead of repeating the guard/baseline/zoom derivation in both functions (Duplicated Code). - Projection2D now carries the live interactive zoom factor (liveZoomK), so Latex2D reads it off the projection it already has instead of a separate 'current-zoom-k' Svelte context threaded through a closure and an `as` cast. - cameraBaseline in CanvasD3 is now set once from the initial camera position instead of being lazily captured from whichever zoom transform happens to fire first, removing the remaining per-instance order-dependence.
Removed doc comments on AxisLabelLayout and normalizeAxisLabelLayout that just restated the type/function name, and an unused svelte-ignore that eslint flagged (cameraBaseline's initializer reads a plain let, not $state, so state_referenced_locally never fires there). Ran prettier and eslint clean.
…xt size Axis tick number labels (and the origin "O") weren't passed fixedScreenScale, so only the x/y axis title labels stayed put on screen while tick numbers kept growing/shrinking with live zoom. Applied fixedScreenScale to all of Axis.svelte's Latex2D calls so tick numbers behave the same way. Also bumped the shared axis label font size (new AXIS_LABEL_FONT_SIZE constant, 1.3x the prior default) since both tick numbers and axis labels were reported as too small; used consistently by Axis.svelte's tick/origin labels and CanvasD3's xLabel/yLabel default. Verified with Playwright against a local production build: effective on-screen text scale (getScreenCTM) stays locked at 1.3 across rest, zoom-in, and zoom-out for tick numbers and axis labels alike.
Axis labels now correctly stay a fixed screen size while zooming, but gridlines, tick marks, and axis lines had their stroke-width specified in world units, so they kept thickening as the user zoomed in - eventually dwarfing the (now fixed-size) tick text next to them. Added vector-effect="non-scaling-stroke" to all of Axis.svelte's grid, tick-mark, and axis lines so their stroke stays a constant screen-pixel width regardless of the ambient zoom transform - the same approach Desmos/GeoGebra use for gridline chrome. stokeWidth()'s return values and the new tick-mark width are now real pixel widths instead of world-unit fractions, since non-scaling-stroke interprets stroke-width in that space. Verified with Playwright against a local production build: gridlines render as thin, constant-width lines at rest and after zooming in, instead of growing thick.
…creen-unit math
- Axis.svelte's 5 <Latex2D> axis-label call sites each repeated
fixedScreenScale={true} + fontSize={AXIS_LABEL_FONT_SIZE} verbatim
(Data Clump / Duplicated Code). Collapsed into one local axisLabel
snippet that bakes in both defaults; call sites now only pass what
differs (latex/position/alignX/alignY/color/offset).
- #492 asked for label placement to stop re-deriving the camera
transform so it has a single owner. The constant (HALF_GRID_SIZE_2D)
was already centralized, but the pixel<->screen-unit conversion
itself was still hand-rolled independently in CanvasD3.svelte's
transformScene (forward) and AxisLabels.ts's getYLabelY (inverse,
recovering the same pixel-space pan for edge-margin math). Extracted
both directions into new CameraViewport.ts (pixelDeltaToScreenUnit /
screenUnitToPixelDelta) and pointed both call sites at it. Same
arithmetic, reordered through one shared function instead of two
independent formulas - existing AxisLabels.test.ts (including the
split-view regression case) passes unchanged, confirming no
behavioural difference.
douden
approved these changes
Sep 15, 2026
douden
left a comment
Collaborator
There was a problem hiding this comment.
Did a quick look, and also checked the diff-images.
To me it looks good 😄
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
AxisLabels.tshad mutable module-global camera-baseline state shared across everyCanvasD3instance, breaking split view. Baseline is now per-canvas state, passed explicitly into puregetXLabelX/getYLabelY. The duplicated15/30base-scale literal is now one constant (HALF_GRID_SIZE_2D/GRID_SIZE_2D), and the pixel/screen-unit conversion that used it is now shared too (CameraViewport.ts), instead of being re-derived separately intransformSceneandAxisLabels.ts.Latex2Dgains afixedScreenScaleprop that counters live zoom viaProjection2D.liveZoomK.fixedScreenScaleto tick numbers, the origin label, and gridline/tick stroke width (non-scaling-stroke), otherwise the title labels stayed fixed-size while everything around them kept scaling, which looked broken rather than fixed. BumpedAXIS_LABEL_FONT_SIZEsince text was reported too small either way. Not asked for by Axis labels are bad with zoom #478 directly, but needed to make the fix actually look done.fixedScreenScale/fontSizeprops acrossAxis.svelte's label call sites into one snippet.This PR changes quite a lot how the applets look like, since now all the axis labels, ticks, etc are screen-size static.