The main purpose of this article is to demonstrate use this package’s image-generating functions. A secondary purpose is to help the package’s developers confirm that these functions continue to work when things get changed.
If you have the packages V8, withr, and fs installed, you can use these image-generating functions to convert vegaspecs (or vegawidgets) into SVG strings or write SVG files. With the rsvg and png packages installed, you can get a bitmap array, or write PNG files.
We have four image-generating functions; they each take either a vegaspec or a vegawidget as their main argument:
vw_to_svg()
returns a string for a SVG imagevw_to_bitmap()
returns a bitmap array that can be
written to a PNG filevw_write_svg()
writes an SVG file, invisibly returns
the vegaspec or vegawidgetvw_write_png()
writes a PNG file, invisibly returns the
vegaspec or vegawidgetAs you can see, the function name indicates the action taken and the image-format.
In addition to a vegaspec or vegawidget, these are the principal arguments:
width
, and height
, sent to
vw_autosize()
to specify the display dimensions. These
refer to the overall dimensions of the image - not the
dimensions of the plotting area.scale
, to support display at retina resolutions. The
default value is 1; for a retina image, you can specify a value of
2.path
, for the image-writing functions, this indicates
the local path to which the file is to be written.As you are most likely already aware, there is a tradeoff between PNG and SVG. The PNG format is an image with finite resolution. The SVG format is a set of instructions on how to render an image, so it has no resolution limitations. In general, the size of an SVG file scales with the number of graphical marks it contains, whereas a PNG file scales with its pixel-width and pixel-height.
If you are using a vegaspec that has dataset loaded from a remote
URL, the V8
scripts will access the remote data using R. If
you use a proxy, make sure it is set up in R.
For the purpose of comparing later renderings, our reference is this
mtcars
scatterplot. It is rendered, in HTML, with a
plotting area of width = 300
and
height = 300
.
spec_mtcars
To use the bitmap and PNG functions, you will need the rsvg and png packages.
The vw_to_bitmap()
function returns a bitmap array. The
package uses it primarily for converting the SVG to PNG; you may have
other uses.
We can show the effect of the scale
argument by
inspecting the dimensions of the bitmap array. Using the default,
scale = 1
:
vw_to_bitmap(spec_mtcars) %>% dim()
## [1] 347 392 4
At scale = 2
:
vw_to_bitmap(spec_mtcars, scale = 2) %>% dim()
## [1] 694 784 4
The function vw_write_png()
uses
vw_to_bitmap()
to write an image-file.
The function vw_write_png()
generates an image at 96
DPI. We will write out a PNG file, then display it at the same
resolution.
Expectation: the image will be rendered at the same size as the reference, but not at retina resolution.
tmp_file <- tempfile(fileext = ".png")
vw_write_png(spec_mtcars, path = tmp_file)
tags$img(src = knitr::image_uri(tmp_file))
We note that the PNG appears slightly different from the HTML rendering. We suspect this is because the SVG-rendering engine, librsvg, works differently from your browser. In the future, we would like to find a way to make the rendering more-similar.
By increasing the scale
to 2, then decreasing the
display-size by a factor of two, we can show this image at “retina”
resolution. The code below is a little tortured, there should be an
easier way. In the future, we would like for this to be the default
method for knitting to a non-HTML medium (using PNG or SVG), and that it
“just work”.
Expectation: the image will be rendered at the same size as the reference, at retina resolution.
tmp_file <- tempfile(fileext = ".png")
vw_write_png(spec_mtcars, path = tmp_file, scale = 2)
tags$img(
src = knitr::image_uri(tmp_file),
onload = "this.width/=2;this.onload=null;"
)
This demonstrates that we can use vw_write_png()
with
vegawidgets.
Expectation: the image will be rendered at the same size as the reference, but not at retina resolution.
tmp_file <- tempfile(fileext = ".png")
vw_write_png(vegawidget(spec_mtcars), path = tmp_file)
tags$img(src = knitr::image_uri(tmp_file))
The vw_to_svg()
function returns an HTML string:
## chr "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.or"| __truncated__
This string can be rendered as standard HTML:
Expectation: this image will appear identical to the reference:
Although the rest of these do not use images, they are included in this article to make it easier to verify that things render as we expect.
Expectation: the rendered spec will have a
total size of width = 600
and
height = 300
.
vw_autosize(spec_mtcars, width = 600, height = 300)
Expectation: we will get the same result using the
vegawidget()
function:
vegawidget(spec_mtcars, width = 600, height = 300)
Expectation: we will get the same result by setting
vega.width
and vega.height
as knitr options,
like so:
```{r vega.width=600, vega.height=300}
spec_mtcars
```
spec_mtcars
Expectation: this will be identical to the reference case, using the
vw_to_vega()
function to compile to a Vega
specification:
vw_to_vega(spec_mtcars)
The purpose of this section is to test the effectiveness of setting
the vega-loader baseURL
as an option.
vw_set_base_url("https://cdn.jsdelivr.net/npm/vega-datasets@2")
cars <-
list(
`$schema` = "https://vega.github.io/schema/vega-lite/v5.json",
width = 300,
height = 300,
description = "A scatterplot showing horsepower and miles per gallons for various cars.",
`data` = list("url" = "data/cars.json"),
mark = "point",
encoding = list(
x = list(field = "Horsepower", type = "quantitative"),
y = list(field = "Miles_per_Gallon", type = "quantitative")
)
) %>%
as_vegaspec()
Expectation: this will be a “live” version of a scatterplot.
cars
Expectation: this will be an SVG version of the scatterplot.