--- title: "Package Development" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Package Development} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} knitr::opts_chunk$set(eval = FALSE) ``` ## Overview You can redistribute your D3 visualizations as reusable components if you bundle them within an R package. There are two ways to accomplish this: 1) Create a wrapper function for the requisite call to `r2d3()` and include that in a package; or 2) Use your D3 script as the basis for the creation of an [htmlwidget](http://www.htmlwidgets.org). This article covers both of these techniques, and also describes how to use the `html_dependencies_d3()` function to include multiple distinct versions of D3 within a document or application. ## R2D3 wrapper function The simplest way to include a D3 visualization you have created with **r2d3** in an R package is to create a wrapper function. There are a few things to keep in mind when creating a wrapper function: 1) You should use `system.file()` for references to the D3 script or any other files (e.g. CSS stylesheets). 2) You should expose any [user level options](visualization_options.html#user-options) as arguments to your wrapper function. 3) You should include `width` and `height` parameters to enable callers of the function to explicitly override your [sizing policy](visualization_options.html#custom-sizing). Here's an example wrapper function which illustrates: ```{r} d3_barchart <- function(data, color = "orange", width = NULL, height = NULL) { r2d3::r2d3( data = data, script = system.file("d3/barchart/barchart.js", package = "d3barchart"), width = width, height = height ) } ``` ## Creating an htmlwidget The `r2d3()` function provides a generic mechanism for turning a standalone D3 visualization script into an [htmlwidget](http://www.htmlwidgets.org). Depending on your requirements, you may find it more convenient to convert your D3 script into a full blown htmlwidget. The [htmlwidgets interface](http://www.htmlwidgets.org/develop_intro.html) provides more granular mechanisms for rendering visualizations, including distinguishing between code for one-time initialization, re-rendering based on new data, and resizing. If you plan on creating an htmlwidget and wish to use version 4 or 5 of D3, please see the section below on [using multiple versions of d3] to ensure that you don't break other widgets that might be relying on an older version of D3. Not that the **r2d3** package also supports an [advanced rendering](advanced_rendering.html) interface that more closely approximates the htmlwidgets API. Converting your visualization to use to the advanced rendering interface is therefore a good first step towards creating an htmlwidget. ## Multiple versions of D3 Many existing [htmlwidgets](http://www.htmlwidgets.org) use version 3 of the D3 library, which has the potential to cause problems when mixed with D3 visualizations that make use of version 4 or 5 of D3. This is because major versions of D3 are incompatible, so using version 4 or 5 with code written for version 3 will result in errors. The **r2d3** package includes an `html_dependencies_d3()` function which enables you to use multiple incompatible versions of D3 within a single document or application. This is accomplished by renaming the global D3 object with a version suffix. So when using `html_dependencies_d3()` the following are the correct references to D3: | Version | Object | |---------------------|---------------------| | 3 | `d3` | | 4 | `d3v4` | | 5 | `d3v5` | For example, if you are using version 4 of D3 then your code might look like this: ```js var outerRadius = Math.min(width, height) * 0.5 - 40, innerRadius = outerRadius - 30; var formatValue = d3v4.formatPrefix(",.0", 1e3); var chord = d3v4.chord() .padAngle(0.05) .sortSubgroups(d3v4.descending); var arc = d3v4.arc() .innerRadius(innerRadius) .outerRadius(outerRadius); var ribbon = d3v4.ribbon() .radius(innerRadius); ``` Note that all references to the D3 library use `d3v4`. Alternatively you could also create a local `d3` alias like this: ```js var d3 = d3v4; var outerRadius = Math.min(width, height) * 0.5 - 40, innerRadius = outerRadius - 30; var formatValue = d3.formatPrefix(",.0", 1e3); var chord = d3.chord() .padAngle(0.05) .sortSubgroups(d3.descending); var arc = d3.arc() .innerRadius(innerRadius) .outerRadius(outerRadius); var ribbon = d3.ribbon() .radius(innerRadius); ``` This local alias technique is in fact what `r3d3()` does when executing D3 visualization scripts so you can always use `d3` to reference the D3 library and know you are getting the correct version. However, if you are [creating an htmlwidget] you will need to be sure to reference the correct version of D3 (i.e. `d3`, `d3v4`, or `d3v4`) explicitly. To incorporate the renamed, multiple-version friendly D3 libraries provided by **r2d3** into an [htmlwidget](http://www.htmlwidgets.org) you can use the `dependencies` argument of the `htmlwidgets::createWidget()` function. For example: ```{r} htmlwidgets::createWidget( "mywidget", x, width = width, height = height, package = "mypackage", dependencies = r2d3::html_dependencies_d3(version = "4") ) ``` ## d3-jetpack The `html_dependencies_d3()` function has can optionally include [d3-jetpack](https://github.com/gka/d3-jetpack) along with D3. Include d3-jetpack by specifying it within the optional `extensions` argument: ```{r} htmlwidgets::createWidget( "mywidget", x, width = width, height = height, package = "mypackage", dependencies = r2d3::html_dependencies_d3(version = "4", extensions = "d3-jetpack") ) ```