Skip to content

vellumwidget 0.5.0

Choose a tag to compare

@schochastics schochastics released this 16 Jul 20:45
· 41 commits to main since this release
  • text argument on as_widget(). Choose how text is written into the SVG,
    passed through to vellum::scene_svg(): "native" (the default) emits
    selectable <text> referencing system fonts — smaller when the page has the
    font, post-processable, and better for accessibility and LLMs — while
    "outline" emits pixel-faithful, font-independent glyph paths. Applies to the
    per-element SVG path only; in raster mode text is baked into the base image and
    the argument is ignored (with a warning if set explicitly) (#1).

  • New articles. Two articles document the features added since 0.4.0:
    Linking views with crosstalk (coordinating a widget with DT / plotly /
    leaflet and crosstalk's filter_* inputs) and Very large scenes (raster
    mode, the spatial index, the columnar payload, and crisp zoom).

  • Crisp zoom in raster mode. When you zoom into a raster-mode plot, the base
    image used to upscale and blur. The widget now redraws the points sharply on a
    <canvas> overlay while zoomed in — sampling each point's colour straight from
    the rendered image and its position/size from the element index, so the crisp
    layer matches what vellum drew. It engages only when zoomed in (the faithful,
    anti-aliased base image still shows at the full view), redraws just the points in
    view, and degrades gracefully to the image alone where a 2D canvas context isn't
    available. Entirely client-side; no change to the payload or to small/moderate
    (SVG-mode) plots.

  • Very large scatterplots are navigable (raster mode). as_widget() gains a
    mode argument ("auto" / "svg" / "raster"). In "auto" (the default), a
    scene with more than raster_threshold keyed elements (default 20000) is drawn
    once as a single embedded image instead of one SVG node per element, and all
    interaction — hover tooltips + highlight, click/brush select, pan/zoom — is driven
    client-side from the element index (bounding boxes + keys) rather than the DOM.
    A 150k-point keyed scatter that previously produced a ~75 MB SVG with 150,000 DOM
    nodes now ships as a ~0.8 MB image plus a compact index, with a handful of DOM
    nodes, and stays smooth to hover and pan. Small and moderate plots are unchanged
    (they keep the per-element SVG). Trade-offs in raster mode: per-element grammar
    colours, per-mark screen-reader focus, and display-tier cross-filtering don't
    apply (there are no per-element nodes), and a zoomed-in view is a scaled raster
    until re-rendered. Adds a dependency on base64enc.

  • Smoother hover, brush, and pan on large plots. Two client-side changes lift
    the per-interaction cost that made big scatterplots laggy:

    • Spatial index. Nearest-mark hover and rectangular brush now hit-test
      against a Flatbush R-tree
      (O(log n) / O(k)) instead of scanning every element each time. The nearest-mark
      scan runs on every pointer move, so this is the change you feel most.
    • Cheaper hover dim. Above a threshold, hovering dims the plot once (via the
      holder's opacity) and re-draws the hovered marks crisply in a small overlay —
      O(hovered) — instead of restyling every element via CSS (O(n)), which forced
      a full-scene style recalc on each hover. Small and moderate plots keep the exact
      previous per-mark dim. (Phase 2 of vellum's big-data interactivity plan.)
  • Much faster, smaller payload for large plots (columnar element table). The
    keyed-element metadata as_widget() embeds is now serialised in a columnar
    form (one array per field) instead of one JSON object per element. This is a
    transparent wire-format change — the widget behaves identically — but it removes
    the per-element serialisation cost that dominated at large N. On a 150,000-point
    keyed scatter the payload build + serialise dropped from ~24 s / 89 MB to
    ~0.4 s / 12 MB
    (~60x faster), so a big interactive scatter is no longer choked
    by payload generation. Small and moderate plots are unaffected. (This is Phase 1
    of vellum's big-data interactivity plan; the browser-side DOM/hover work for
    truly huge scatters follows in later phases.)

  • Error bars and boxplots are interactive. Now that vellumplot keys these
    statistical marks, the widget hovers, tooltips, clicks/selects, and brushes them
    as units: an error bar's bar + caps, or a box's rect + median + whiskers, all
    light up and select together because they share one data-key (outliers stay
    individually addressable). Brush selection no longer double-counts a mark whose
    key spans several SVG elements — input$<id>_brush$keys reports each such key
    once. No runtime change was needed for the core behaviour; it already grouped
    every node sharing a key.