Skip to content

Fix AxisLabels module-global state and stop re-deriving the camera transform #492

Description

@bewuwy

Problem

AxisLabels.ts exposes two functions — getXLabelX and getYabelY (note the misspelling, propagated to the call site) — that look pure but carry mutable module-global state:

let cameraBaselineX: number | undefined;   // AxisLabels.ts:17-18
let cameraBaselineY: number | undefined;

These are lazily captured on the first call (revertCameraBaseline) and never reset. Consequences:

  • Output depends on invocation order and prior calls — the least testable code in the 2D layer.
  • Split view is broken by design: two canvases on one page (Canvas2D split mode) share the same module globals, so the first canvas to render sets the baseline for both.

On top of that, the functions reverse-engineer the world→screen transform that CanvasD3 already applied. The base-scale constant 15 (half of GRID_SIZE_2D) is typed literally in four places that must stay in agreement:

  • ViewBox.ts:40 — zoom (15 / boxWidth)
  • CanvasD3.svelte:196 — the forward SVG transform (scale(2*width/30, ...))
  • CanvasD3.svelte:103 — the inverse in transformScene (15 / (width / x))
  • AxisLabels.ts:65,88,89 — re-derivation of world coordinates from the D3 transform

Any change to the base scale requires edits in all four.

Solution

  • Replace the module-global baseline with instance state, so split canvases stop sharing it.
  • Have label placement ask the Projection2D module (see related issue) for toWorld/toScreen instead of re-deriving the transform, so the constant 15 has a single owner.

Benefits

  • Locality: the world↔screen transform has one owner; the constant stops being copied four ways.
  • Split canvases no longer share baseline state — fixes a live correctness defect.
  • Label math becomes order-independent pure functions, testable in isolation.

Affected files

AxisLabels.ts:17-18,42,73, CanvasD3.svelte:103,196,179-182, ViewBox.ts:40.

Related

Depends conceptually on the Projection2D seam (#491). The module-global mutable state is a real bug in split view and is worth fixing regardless of whether Projection2D lands first.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions