Skip to contents

vellumverse is a meta-package: it holds no plotting code of its own. Its job is to install and attach the three packages that make up the vellum graphics ecosystem, so that

library(vellumverse)
#> ── Attaching packages ──────────────────────────────── vellumverse 0.3.3.9000
#> ──
#> ✔ vellum 0.6.6.9000 ✔ vellumplot 0.9.0
#> ✔ vellumwidget 0.8.0.9000
#> ── Conflicts ──────────────────────────────────────── vellumverse_conflicts() ──
#> ✖ vellumplot::linear_gradient masks vellum
#> ✖ vellumplot::md              masks vellum
#> ✖ vellumplot::pdf_pages       masks vellum
#> ✖ vellumplot::radial_gradient masks vellum
#> ✖ vellumplot::render_all      masks vellum
#> ✖ vellumplot::sketch          masks vellum
#> ✖ vellumplot::vl_pattern      masks vellum

puts all of them on your search path at once. Each one owns a distinct layer of the stack, and the design intent is that you rarely think about the boundaries between them.

Three layers, one scene

The parchment, the pen, and the annotation each have a name:

layer package what it is the tidyverse analogue
backend vellum a scene graph, unit/layout engine, and PNG/SVG/PDF renderer that also reports the geometry it resolved grid
grammar vellumplot a pipe-first grammar of graphics that compiles a plot spec into a vellum scene ggplot2
interaction vellumwidget turns a vellum scene into a self-contained interactive HTML widget htmlwidgets

The important word is compiles. A vellumplot plot is not drawn as you build it; it is an inspectable specification that is turned into a vellum scene only when it is printed, rendered, or handed to vellumwidget. Everything below is therefore one scene passing down the stack.

vellum: the parchment

vellum is the foundation. You describe a scene with a small declarative API and render it. Because it measures text and solves layout in process rather than asking a device, one solved scene draws to raster or vector with the same geometry — and, once solved, it can tell you that geometry: scene_model() returns a row per drawn element with its data key and device-pixel box, and hit_test() says which node is under a point. That read-back is what the layer above the grammar is built on.

vl_scene(width = 4, height = 2.4, bg = "white") |>
  draw(rect_grob(
    width = 0.9, height = 0.8,
    gp = vl_gpar(fill = linear_gradient(c("#6b4f2c", "#c9a86a")), col = NA)
  )) |>
  draw(text_grob(
    "vellum", x = 0.5, y = 0.5,
    gp = vl_gpar(fontsize = 44, col = "white", fontface = "bold")
  ))

You would reach for vellum directly to build a bespoke visual, or as the target of a higher-level tool, which is exactly what vellumplot is.

vellumplot: the pen

vellumplot gives you the grammar: data in, marks and scales declared with tidy evaluation, everything trained and laid out for you.

vplot(mtcars) |>
  mark_point(x = wt, y = mpg, color = hp) |>
  scale_color_continuous()

Because the plot is a spec, you can inspect it without drawing anything:

summary(vplot(mtcars) |> mark_point(x = wt, y = mpg, color = hp))
#> <PlotSpec> 32x11 (11 columns), page 6x4 in
#>
#> ── layers
#> • mark_point(x = wt, y = mpg, color = hp)

vellumwidget: the annotation

vellumwidget is terminal: hand it a vellumplot plot (or a bare vellum scene) and it compiles the scene, emits the SVG plus a per-element table, and returns an htmlwidget with hover tooltips, selection, brushing, and pan/zoom, with no Shiny and no server.

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()

The tooltip and data_id arguments are declared in vellumplot, read by vellumwidget, and carried through the vellum scene: the three layers agreeing on one contract.

Where each package’s docs live

vellumverse is the front door; each package documents itself in full:

  • vellum: grobs, units, viewports, the paint model, datashade(), and grid interop.
  • vellumplot: the full mark, scale, facet, coord, and theme reference.
  • vellumwidget: interaction options, linked views, and crosstalk interop.