Canvas Options

library(gglite)
# This document uses non-default renderers (SVG and WebGL). Declare this
# option globally so all renderers can work on the same page.
options(gglite.renderer = 'svg')

1 Dimensions

By default a chart auto-fits its container width and uses a height of 480 px. Use canvas() to override:

p = g2(mtcars, hp ~ mpg)
p |> canvas(width = 500, height = 300)

2 Layout Spacing

padding is the space between the container edge and the plot area. margin adds space outside the container. inset adds space inside the plot area, pushing axis tick labels inward. Each argument accepts a scalar (all sides) or c(top, right, bottom, left) with NA to skip individual sides.

p |>
  canvas(margin = 10, padding = c(10, 150, NA, 100), inset = c(10, 0, 20, -20)) |> 
  theme_light(view = list(viewFill = '#fff3bf', plotFill = '#ffc9c9', mainFill = '#a5d8ff'))

3 Renderer

G2 ships two bundles with different trade-offs:

renderer Scripts loaded Approx. total size
"Canvas" (default and optimized) g2.min.js ~1.1 MB
"Canvas" (via g2.lite) @antv/g + @antv/g-canvas + g2.lite.min.js ~1.5 MB
"SVG" @antv/g + @antv/g-svg + g2.lite.min.js ~1.5 MB
"WebGL" @antv/g + @antv/g-webgl + g2.lite.min.js ~1.9 MB

SVG output can be inspected element-by-element in browser DevTools and is therefore well suited to automated DOM-based testing. WebGL is GPU-accelerated and handles very large numbers of data points with less rendering time.

3.1 Caveat: multi-chart documents

g2.min.js and g2.lite.min.js cannot coexist on the same HTML page. In a document that contains multiple charts — such as an R Markdown, Quarto, Shiny, or Jupyter document — setting options(gglite.renderer) explicitly makes sure all plots use g2.lite.min.js and avoids loading g2.min.js:

options(gglite.renderer = 'svg')   # or 'webgl', 'canvas'

Individual charts can still override the renderer via canvas(renderer = ...). For example, when options(gglite.renderer = 'svg') is active, a specific chart can use canvas(renderer = 'webgl') — both use g2.lite.min.js so they do not conflict.

For standalone plots previewed in the browser (printed from the console of an interactive R session), each plot is its own HTML page, so no global option is needed.

p |> canvas(renderer = 'svg')
p |> canvas(renderer = 'webgl')
p |> canvas(renderer = 'canvas')

4 Extra Options

The ... argument in canvas() passes additional top-level options to chart.options() in JavaScript. For example, clip controls whether marks that extend beyond the plot area are clipped:

# clip = FALSE (default): marks can overflow the plot area
p |> scale_y(domain = c(80, 220)) |> canvas(clip = FALSE)
# clip = TRUE: marks are clipped to the plot area
p |> scale_y(domain = c(80, 220)) |> canvas(clip = TRUE)

5 WebGL for Large Datasets

WebGL is GPU-accelerated and can render far more data points than Canvas or SVG before frame time degrades. The example below uses 200,000 flight records (distance vs. departure delay) to illustrate this.

g2("https://vega.github.io/vega-datasets/data/flights-200k.json") |>
  encode(delay ~ distance) |>
  mark_point() |>
  style_mark(size = 2, fillOpacity = 0.2) |>
  canvas(renderer = 'webgl')

However, it wouldn’t render on my M1 macOS and could even freeze my browser, and I don’t know why…