Save a ggplot2, lattice or Base R plot as an HTML file with interactive MAIDR accessibility features.
Usage
save_html(
plot = NULL,
file = "plot.html",
use_cdn = NULL,
width = NULL,
height = NULL,
...
)Arguments
- plot
A ggplot2 object, a lattice (trellis) object, or NULL for Base R auto-detection
- file
File path where to save the HTML file (e.g., "plot.html")
- use_cdn
Logical. Controls where MAIDR.js is loaded from:
TRUE: Use CDN. The file is self-contained but needs internet access when it is viewed. It names the latest published MAIDR.js by version (looked up once per R session, or the bundled version when the lookup cannot be made); pin a version withoptions(maidr.cdn_version = ...), see?"maidr-options".FALSEorNULL(default): Use the bundled files. The MAIDR.js library is written to alib/folder besidefile, which has to travel with it.
- width, height
The size to draw the chart at, in inches: each a single positive number no larger than 50, or
NULL(the default) for 7 x 5 in, 12 x 6 in for a candlestick chart. A side not given takes its default. See Chart size.- ...
Additional arguments passed to internal functions
Details
By default the MAIDR.js library is written to a lib/ folder beside
file, and the two have to be shared together: zip the folder that
holds both, or copy both. An .html sent on its own loads no
MAIDR.js and shows a plain, inaccessible chart. use_cdn = TRUE
writes one self-contained file instead, which needs internet access
whenever it is viewed and loads the latest published MAIDR.js from
jsDelivr rather than the copy bundled with this package.
Base R charts
A Base R chart is read from the plotting calls recorded on the current
device, and is the page that device shows: the last one. R draws a
high-level plot on a new page when it moves past the last panel of the
page it is on – every plot on a page of one panel, the fifth under
par(mfrow = c(2, 2)), the first after par(mfrow = ), par(mfcol = )
or layout() sets a page up again – and plot.new() and frame()
move on a panel as a plot does. So after hist(a); hist(b) the chart is
the histogram of b alone, and after five plots under
par(mfrow = c(2, 2)) it is the fifth, in the first panel of a 2 x 2
grid. Each plot of a grid is in the panel R drew it in: a plot drawn
after par(new = TRUE), or with add = TRUE, is drawn in the panel of
the plot before it, one par(mfg = ) sends to a panel out of turn is in
that panel, and a panel plot.new() or frame() passed over stays
empty. So it is where the call that set the grid up was not recorded:
one made through graphics::par() or graphics::layout(), before
maidr_on(), or before an earlier show() or save_html() on the
device. A plot drawn in a region of the page par(fig = ) gave it, as
an inset is, or in a screen of split.screen(), is drawn in that
region, and read with the plot before it. lines(), points(),
abline(), text(), legend(), title(), axis() and the other
low-level calls add to the plot they are drawn on: after par(mfg = ),
or screen(n, new = FALSE) of split.screen(), sends R back to the
panel or screen of an earlier plot, to that plot. Drawn on a panel
plot.new() or frame() took, as a legend of its own is, or on a plot
maidr does not record, such as smoothScatter(), they are drawn there,
and read as part of no plot. Drawn over a plot after par(new = TRUE)
and plot.new(), as a second series with an axis of its own is – also
over the plot of an earlier panel or screen par(mfg = ) or screen()
sent R back to – they are drawn in the coordinates they were drawn in,
and read with that plot. Nothing drawn on an earlier page reaches the
chart: not its data, its titles or the size it is drawn at. A page
replayPlot() puts back,
from a plot recordPlot() saved on a device that keeps a display list,
is the page the chart is read from, with what was drawn on it when it
was saved and what has been drawn on it since. A page that holds no plot
maidr recorded – one R started with plot.new() or frame(), with a
plot maidr does not record, or with one drawn while maidr_off() was in
effect, even with lines() or text() drawn on it since, or one
replayPlot() put back from such a page, or from a plot saved in
another session or on another device – is not read as the plot before
it: show() and save_html() stop, and say so. Each
figure of an R Markdown or Quarto document is read the same way, from
the calls on its own page.
Chart size
A chart is drawn at a size in inches, as ggplot2::ggsave() and knitr's
fig.width and fig.height size a figure, and its SVG is 72 pixels to
the inch: a 10 x 4 in chart is 720 pixels wide and 288 high. The size is
the room the chart is laid out in – how far apart its ticks and labels
are, how lattice arranges its panels, where Base R puts its titles – and
not what maidr reads out: the data, titles and axis labels a reader
hears are the same at every size. Only how a reader moves between panels
can change: lattice arranges the panels of a chart conditioned on one
variable with no layout = for the shape of the page, 1 x 2 at 7 x 5 in
and 2 x 1 at 5 x 8 in for two panels, and the subplot grid a reader
moves through follows; give layout = to keep it. The size is set by
width and height in show() and save_html(), by fig_width and
fig_height in
render_maidr(), and by the chunk's fig.width and fig.height in an
R Markdown or Quarto document (see maidr_on()). Nothing else sets it:
not the size of the device a chart was drawn on, nor the size of the
window, viewer or Shiny output it is shown in, which shrinks a chart
wider than itself to fit.
Unset, a chart is 7 x 5 in. A candlestick chart is 12 x 6 in, and is
never drawn smaller than that: quantmod's chartSeries() needs the room
for its title, date range and date labels. A smaller size asked for is
enlarged, with a message naming the size the chart is drawn at. A side
larger than 50 in is refused, as ggplot2::ggsave() refuses one: the
size is in inches, not the pixels maidr_output() takes.
A Base R chart's margins and text take the same room at every size, as
do the cells a layout() call sizes with lcm(), so a chart can be too
small for them – R itself stops with "figure margins too large", or for
those cells "figure region too large", at such a size. maidr draws the
chart with the margins and text size its par() calls set, so it fits
where R draws it with them.
Asked for a size too small, maidr stops too, with an error naming the
size, rather than show an empty chart: draw it larger. With no size
asked for, a chart too small for 7 x 5 in, such as a par(mfrow) grid
of five rows or more, is drawn on the 7 x 7 in page maidr laid every
Base R chart out on before it drew one at its size. Where that is too
small too, it is drawn on the smallest larger page that leaves each of
its plots a sixth of an inch, 12 px, each way, each side grown in whole
inches only as far as it needs: 7 x 9 in for six rows, 12 x 5 in for
twelve columns. A message names the size it is drawn at. The picture of a
Base R chart maidr cannot read is held to its size in the same way.
Examples
# ggplot2 bar chart
library(ggplot2)
p <- ggplot(mtcars, aes(x = factor(cyl), y = mpg)) +
geom_bar(stat = "identity")
# \donttest{
maidr::save_html(p, tempfile(fileext = ".html"))
# The same chart, 10 inches wide and 4 high
maidr::save_html(p, tempfile(fileext = ".html"), width = 10, height = 4)
# }
# ggplot2 violin plot
p_violin <- ggplot(mtcars, aes(x = factor(cyl), y = mpg)) +
geom_violin(fill = "lightblue", alpha = 0.7) +
labs(title = "MPG by Cylinders", x = "Cylinders", y = "MPG")
# \donttest{
maidr::save_html(p_violin, tempfile(fileext = ".html"))
# }
# lattice chart [experimental]
# \donttest{
if (requireNamespace("lattice", quietly = TRUE)) {
p_lattice <- lattice::bwplot(factor(cyl) ~ mpg, data = mtcars)
maidr::save_html(p_lattice, tempfile(fileext = ".html"))
}
# }
# Base R example (requires interactive session for function patching)
if (interactive()) {
barplot(c(10, 20, 30), names.arg = c("A", "B", "C"))
maidr::save_html(file = tempfile(fileext = ".html"))
}