
Turn a vellum scene (or vellumplot plot) into an interactive widget
Source:R/as-widget.R
as_widget.Rdas_widget() is the terminal verb of the interactivity pipeline: it compiles
its input to a vellum scene, emits the SVG (with per-element data-keys) and
the vellum::scene_model() element table, and bundles them with the vellumwidget
JavaScript runtime into a self-contained htmlwidgets::createWidget() widget.
The result does hover tooltips, hover highlighting, and click selection
entirely client-side — no Shiny, no server round-trip. Pan/zoom, brush, and
selection work with mouse, touch (drag to pan, two-finger pinch to zoom), and
keyboard input: the arrows pan and +/-/0 zoom and reset, except that with
accessibility on (the default) the arrows move between marks while one is
focused — see the a11y argument.
Usage
as_widget(
x,
width = NULL,
height = NULL,
toolbar = TRUE,
navigator = FALSE,
navigator_height = NULL,
hover_mode = c("closest", "x", "y"),
crosshair = FALSE,
legend_click = c("select", "hide", "mute"),
a11y = TRUE,
alt = NULL,
tooltip_delay = 0,
tooltip_follow = TRUE,
tooltip_sticky = FALSE,
tooltip_style = NULL,
export_filename = NULL,
export_scale = NULL,
group = NULL,
crosstalk = NULL,
select_mode = c("multiple", "single"),
mode = c("auto", "svg", "raster"),
raster_threshold = 20000L,
text = c("native", "outline"),
elementId = NULL
)Arguments
- x
A
vellumplotplot (aPlotSpec/PlotComposition) or avellumscene — anythingvellum::as_vellum_scene()accepts. Also a keyframe animation fromvellumplot::animate(), embedded as a self-contained animated SVG that plays on its own (no per-element interaction).- width, height
Widget size (any valid CSS size, or
NULLto size from the scene). Passed tohtmlwidgets::createWidget().- toolbar
Show the on-hover toolbar (default
TRUE). Hover tooltip, highlight, click-select, brush, lasso, pan/zoom, and axis-aware zoom are on by default (interactive-by-default) and no longer have per-widget toggles; per-mark hover/select styling and selection-driven behaviour are declared in the plot spec instead (seevellumplot::condition()/vellumplot::select_point()).Show an overview range navigator below the plot (default
FALSE): a full-width strip rendering the whole scene in miniature, with a draggable, resizable window marking the visible x-range. Drag the window to pan, drag a handle to zoom; it stays two-way in sync with the main view (wheel/keyboard/brush and linked-group changes all move it). Useful for long series.navigator_heightsets the strip height in pixels (default56).Height of the navigator strip in pixels (default
56); ignored unlessnavigator = TRUE.- hover_mode
How hover gathers marks into the tooltip.
"closest"(default) shows the single nearest mark."x"(or"y") gives a unified hover: every mark sharing the hovered x (or y) position is highlighted and listed together in one box — the shared readout multi-series line and time-series charts expect. Unified mode always snaps along its axis, so the readout tracks the cursor regardless ofnearest. The mark positions come from the element index, so no axis metadata is required; the box lists each mark'stooltip(one row per series) without a value-axis header.- crosshair
Draw a guide rule at the hovered position (default
FALSE): a vertical rule at the shared x whenhover_mode = "x", a horizontal rule when"y", and a full cross through the mark when"closest". Colour is the--vellumwidget-crosshair-strokeCSS variable (a muted grey by default).- legend_click
What clicking a discrete-legend swatch does.
"select"(default) selects the swatch's whole series (the established behaviour)."hide"makes the legend a visibility toggle — a single click hides/shows the series, a double-click isolates it (hides every other series; double-click again to restore all) — the reflexive legend interaction in plotly / ECharts / Highcharts."mute"is the same but dims the series instead of removing it (its layout is kept). Hovering a swatch still highlights its series under every policy. Applies only where the plot draws an interactive legend (a discretecolor/shapescale invellumplot).- a11y
Accessibility (default
TRUE). Makes the widget a keyboard- and screen-reader-navigable chart: the SVG is labelled as an interactive chart (role="graphics-document"), each mark is a focusablegraphics-symbolwith a roving tabindex (arrow keys move between marks, Enter/Space select, Escape exits), a politearia-liveregion announces the focused/selected mark, and a visually-hidden data table lists every mark for assistive tech.FALSErestores the previous behaviour (no chart semantics, marks not focusable).- alt
Accessible label (alt text) for the chart as a whole. Defaults to the scene's own title/description — which
vellumplotsets automatically from the plot title andvellumplot::plot_alt()— so an explicit value is only needed for a rawvellumscene or to override.- tooltip_delay
Milliseconds to wait before the tooltip appears on hover (default
0, i.e. immediate). The highlight is unaffected — only the tooltip waits. A short delay (e.g.250) calms a dense scatter.- tooltip_follow
When
TRUE(default) the tooltip tracks the cursor; whenFALSEit anchors above the hovered mark's centre.- tooltip_sticky
When
TRUE, the tooltip accepts pointer events and lingers briefly when you leave the mark, so you can move into it — for tooltips that contain links or buttons (build the HTML viatooltip =). DefaultFALSE.- tooltip_style
Optional named list styling the tooltip box:
background/color(any R or CSS colour),fontsize, andmax_width(any CSS length).NULL(default) uses the built-in style. Tooltip text is rendered as safe HTML — an author-builttooltip =(e.g. viaglue()) may use<b>/<i>/<br>for bold/italic/line breaks; data values are escaped and only those inert tags are honoured (no scripts/attributes).- export_filename, export_scale
The download filename base (no extension; default
"plot") and the PNG resolution multiplier (default1) for the toolbar's SVG/PNG export. Exports capture the current (zoomed/panned) view.- group
Optional linking group name. Widgets sharing a
grouplink client-side: selecting (or brushing) in one highlights the same data keys in the others, and panning/zooming one pans/zooms the others to the same relative view — no Shiny, no crosstalk. Selection projects byhover_groupwhen the marks declare it (select one, select the whole series). Linked pan/zoom shares the view as a fraction of each widget's own extent, so it links correctly even across differently-sized plots (e.g. small multiples).- crosstalk
Optional crosstalk::SharedData (or a crosstalk group name string) to link this widget with the crosstalk ecosystem (plotly, leaflet, DT, and crosstalk's
filter_*inputs). The widget'sdata_ids must match the SharedData's keys. A crosstalk filter hides the non-matching elements (display-tier cross-filter). Requires the crosstalk package.- select_mode
"multiple"(default; click toggles each element) or"single"(click replaces the selection).- mode
Rendering strategy for the marks.
"auto"(default) ships a per-element SVG for small/moderate plots and switches to a single embedded raster image aboveraster_thresholdkeyed elements;"svg"always uses the per-element SVG;"raster"always uses the image. In raster mode the marks are drawn once as a base image and all interaction (hover, click, brush, pan/zoom) is driven client-side from the element index (geometry + boxes + keys), so a very large scatter (100k+ points) stays navigable with a tiny DOM and a small payload. The trade-offs of raster mode: per-element grammar colours, per-mark screen-reader focus, and display-tier cross-filtering do not apply (there are no per-element DOM nodes), and a zoomed-in view is a scaled raster until re-rendered.- raster_threshold
Keyed-element count above which
mode = "auto"switches to the raster image (default20000).- text
How text is written into the SVG, passed to
vellum::scene_svg():"native"(default) emits selectable<text>referencing system fonts — smaller when the page has the font, post-processable, and better for accessibility and LLMs;"outline"emits glyph outlines that are pixel-faithful and font-independent but not selectable. Applies to the per-element SVG path only; in raster mode (seemode) text is baked into the base image and this argument is ignored (with a warning if set explicitly).- elementId
Optional explicit widget DOM id.
Details
Interactivity is driven by the keys/metadata a plot declares. In vellumplot these
come from the reserved data_id / tooltip / hover_group mark arguments; a
plot that declares none renders as a static (but still embeddable) SVG. A
hovered element with a data_id but no tooltip shows its key.
Graph (vgraph()) plots that declare vellumplot::select_neighbours() are
enacted here: hovering a node spotlights its neighbourhood (the node, its
incident edges, and its adjacent nodes) and dims the rest, and hovering an edge
spotlights its two endpoints. The adjacency is reconstructed from the endpoint
identity each edge carries — no extra configuration.
The scene metadata vellumwidget reads — the vellum::scene_model() element
table and the SVG data-key / data-vellum-* attributes — is specified in
vellum's "The scene contract" vignette
(vignette("scene-contract", package = "vellum")).
Examples
if (FALSE) { # \dontrun{
library(vellumplot)
df <- data.frame(wt = mtcars$wt, mpg = mtcars$mpg, model = rownames(mtcars))
vplot(df) |>
mark_point(x = wt, y = mpg, tooltip = model, data_id = model) |>
as_widget()
} # }