Skip to content

Mark every served sample, and make an enum lane an ordinary series - #499

Merged
thebhef merged 1 commit into
mainfrom
task146-markers
Oct 4, 2026
Merged

thebhef merged 1 commit into
mainfrom
task146-markers

Conversation

@thebhef

@thebhef thebhef commented Sep 21, 2026

Copy link
Copy Markdown
Owner

Two plot-panel defects with one cause between them: two mechanisms were
each deciding where a marker goes, and neither was choosing well.

Points: On looked like extrapolation. It thinned markers to a flat
500 across the visible range on a uniform index stride. A uniform stride
over a min/max envelope aliases onto one leg of it, so the dots hugged
one side of a line that was oscillating through both and most extrema
carried none at all — the markers were on the line, the wrong ones were
being chosen. The cap is gone: on marks every served sample. Nothing
is unbounded by that, because the serve already is, to a few points per
canvas pixel column.

An enum lane is now an ordinary series with an overlay on top. It is
served, plotted and marked exactly as a numeric stepped series is (the
host half landed in the previous commit), and the tiles are an overlay
computed from runs of equal consecutive served values — shaping
already-paged data for the renderer, not re-deriving a model fact. The
lane's private marker pass is deleted, and with it the reason it existed:

  • the tiles draw in the drawAxes hook, under the series layer,
    so uPlot's markers land on a tile instead of beneath 65-85 % of
    opacity. Only the labels are held back for the draw hook — a tile's
    label is the only place the held value's name appears, and the one
    part of a lane the waveform may not cross;
  • a code is normalised into the tile band rather than the whole lane
    band. The tile is the centred 60 % of the lane, so a table's extreme
    codes used to plot in the gap between lanes — for a two-code enum,
    code 0 sat below its own tile entirely — and a marker on the plotted
    value landed off the tile it belongs to;
  • a lane's marker ink is measured against the tile the way its label's
    already is: the accent wherever it clears 3:1, otherwise the extreme
    opposite the theme's background. One ink per lane, because whether the
    accent survives a tinted tile is a property of the theme rather than
    of the value. The single-enum ribbon keeps the plain accent — its line
    plots the real code against a real y scale, so its markers are as
    often off the ribbon as on it.

What a lane loses is its exemption from uPlot's density rule under
auto; it now falls under the same rule, and the same minimum-sample
floor, as a slow line on a shared axis. That is the point of unifying
them.

The categorical fetch flag goes with the host's reducer, so
DecimatedRequest no longer carries a render mode and the fetch memo
key no longer keys on one.

Reviewers: the draw-order change is the load-bearing part — tiles before
the series layer, labels after — and PlotArea.draw.test.ts drives both
passes the way uPlot runs them. The new cases there pin a marker per
served sample with no stride, a lane's markers coming from the shared
points.filter, no marker left on a cell the extrapolation blanking
takes, and a held state arriving as one tile at the window width and
point budget the categorical serve was introduced against.

Co-Authored-By: Claude Fable 5.1 noreply@anthropic.com

This was referenced Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant