作者:Yihui Xie
译者:郑宝童
日期:2021.05.27


2.10 HTML小部件

Although one of R’s greatest strengths is data visualization, there are a large number of JavaScript libraries for much richer data visualization. These libraries can be used to build interactive applications that can easily render in web browsers, so users do not need to install any additional software packages to view the visualizations. One way to bring these JavaScript libraries into R is through the htmlwidgets package (Vaidyanathan et al. 2020).

虽然R最大的优点之一是数据可视化,但是有大量的JavaScript库也可以实现更丰富的数据可视化。这些库可以用来构建可以轻松在web浏览器中呈现的交互式应用程序,因此用户不需要安装任何额外的软件包来查看可视化。将这些JavaScript库引入R的一种方法是通过htmlwidgets包(Vaidyanathan等人。2020)。

HTML widgets can be rendered as a standalone web page (like an R plot), or embedded in R Markdown documents and Shiny applications. They were originally designed for HTML output only, and they require the availability of JavaScript, so they will not work in non-HTML output formats, such as LaTeX/PDF. Before knitr v1.13, you will get an error when you render HTML widgets to an output format that is not HTML. Since knitr v1.13, HTML widgets will be rendered automatically as screenshots taken via the webshot package (Chang 2019). Of course, you need to install the webshot package. Additionally, you have to install PhantomJS (http://phantomjs.org), since it is what webshot uses to capture screenshots. Both webshot and PhantomJS can be installed automatically from R:

HTML小部件可以呈现为一个独立的网页(比如R图),或嵌入R Markdown文档和shiny的应用程序。它们最初是为HTML输出而设计的,并且它们需要JavaScript的可用性,所以它们不能在非HTML输出格式(如LaTeX/PDF)中工作。在knitr v1.13之前,当将HTML小部件呈现为非HTML的输出格式时,将会得到一个错误。自knitr v1.13起, HTML小部件将通过webshot包自动呈现为截图(Chang 2019),当然,您需要安装webshot包。另外,你必须安装PhantomJS (http://phantomjs.org),因为它是webshot用来捕获屏幕截图的。webshot和PhantomJS都可以在R自动安装:

  1. install.packages("webshot")
  2. webshot::install_phantomjs()

The function install_phantomjs() works for Windows, OS X, and Linux. You may also choose to download and install PhantomJS by yourself, if you are familiar with modifying the system environment variable PATH.

函数install_phantomjs()适用于Windows、OS X和Linux。如果您熟悉修改系统环境变量PATH,也可以选择自己下载并安装PhantomJS。

When knitr detects an HTML widget object in a code chunk, it either renders the widget normally when the current output format is HTML, or saves the widget as an HTML page and calls webshot to capture the screen of the HTML page when the output format is not HTML. Here is an example of a table created from the DT package (Xie, Cheng, and Tan 2021):
knitr在代码块中检测到HTML小部件对象时,它要么在当前输出格式为HTML时正常呈现小部件,要么将小部件保存为HTML页面,并在输出格式不是HTML时调用webshot来捕获HTML页面的屏幕。下面是一个从DT包创建的表的示例(Xie, Cheng, and Tan 2021):

  1. DT::datatable(iris)

Show 102550100 entries
Search:

Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
7 4.6 3.4 1.4 0.3 setosa
8 5 3.4 1.5 0.2 setosa
9 4.4 2.9 1.4 0.2 setosa
10 4.9 3.1 1.5 0.1 setosa

Showing 1 to 10 of 150 entries
Previous12345…15Next
FIGURE 2.5: A table widget rendered via the DT package.

If you are reading this book as web pages now, you should see an interactive table generated from the above code chunk, e.g., you may sort the columns and search in the table. If you are reading a non-HTML version of this book, you should see a screenshot of the table. The screenshot may look a little different with the actual widget rendered in the web browser, due to the difference between a real web browser and PhantomJS’s virtual browser.

如果你现在正以网页的形式阅读这本书,你应该会看到一个由上面的代码块生成的交互式表格,例如,你可以在表格中对列进行排序和搜索。如果您正在阅读这本书的非html版本,您应该会看到表格的屏幕截图。由于真实的web浏览器和PhantomJS的虚拟浏览器之间的差异,屏幕截图看起来可能与web浏览器中呈现的实际小部件略有不同。

There are a number of knitr chunk options related to screen-capturing. First, if you are not satisfied with the quality of the automatic screenshots, or want a screenshot of the widget of a particular state (e.g., after you click and sort a certain column of a table), you may capture the screen manually, and provide your own screenshot via the chunk option screenshot.alt (alternative screenshots). This option takes the paths of images. If you have multiple widgets in a chunk, you can provide a vector of image paths. When this option is present, knitr will no longer call webshot to take automatic screenshots.

有许多与屏幕捕获相关的knitr 块选项。首先,如果你不满意自动截图的质量,或者想要小部件的一个特定状态的一个屏幕快照(例如,当你点击某个列进行排序的表),您可以手动捕获屏幕,通过块选项screenshot.alt (alternative screenshots)提供自己的截图。此选项要用到图像的路径。如果一个块中有多个小部件,则可以提供图像路径的向量。当这个选项是存在的,knitr将不再调用webshot自动截屏。

Second, sometimes you may want to force knitr to use static screenshots instead of rendering the actual widgets even on HTML pages. In this case, you can set the chunk option screenshot.force = TRUE, and widgets will always be rendered as static images. Note that you can still choose to use automatic or custom screenshots.

其次,有时您可能希望强制knitr使用静态截图,而不是在HTML页面上呈现实际的小部件。在这种情况下,您可以设置块选项 screenshot.force = TRUE,小部件将始终呈现为静态图像。请注意,您仍然可以选择使用自动或自定义的截图。

Third, webshot has some options to control the automatic screenshots, and you may specify these options via the chunk option screenshot.opts, which takes a list like list(delay = 2, cliprect = 'viewport'). See the help page ?webshot::webshot for the full list of possible options, and the package vignette vignette('intro', package = 'webshot') illustrates the effect of these options. Here the delay option can be important for widgets that take long time to render: delay specifies the number of seconds to wait before PhantomJS takes the screenshot. If you see an incomplete screenshot, you may want to specify a longer delay (the default is 0.2 seconds).

第三,webshot有一些选项来控制自动截图,你可以通过chunk选项screenshot.opts来指定这些选项。它接受一个列表,如list(delay = 2, cliprect = 'viewport')。请t通过?webshot::webshot查看帮助页面 以获得完整的可能选项列表, package vignette vignette('intro', package = 'webshot') 演示了这些选项的效果。这里的delay选项对于需要很长时间渲染的小部件来说很重要:delay指定在PhantomJS截取截图之前等待的秒数。如果你看到一个不完整的屏幕截图,你可能想要指定一个更长的延迟(默认是0.2秒)。

Fourth, if you feel it is slow to capture the screenshots, or do not want to do it every time the code chunk is executed, you may use the chunk option cache = TRUE to cache the chunk. Caching works for both HTML and non-HTML output formats.

第四,如果您觉得捕获屏幕截图很慢,或者不想每次执行代码块时都这样做,您可以使用chunk选项cache = TRUE来缓存该块。缓存可以同时用于HTML和非HTML输出格式

Screenshots behave like normal R plots in the sense that many chunk options related to figures also apply to screenshots, including fig.width, fig.height, out.width, fig.cap, and so on. So you can specify the size of screenshots in the output document, and assign figure captions to them as well. The image format of the automatic screenshots can be specified via the chunk option dev, and possible values are pdf, png, and jpeg. The default for PDF output is pdf, and it is png for other types of output. Note that pdf may not work as faithfully as png: sometimes there are certain elements on an HTML page that fail to render to the PDF screenshot, so you may want to use dev = 'png' even for PDF output. It depends on specific cases of HTML widgets, and you can try both pdf and png (or jpeg) before deciding which format is more desirable.

截图(Screenshots )与普通的R plot在操作上类似,因为许多与图形相关的块选项也适用于截图(Screenshots ),包括fig.width, fig.height, out.width, fig.cap等等。因此,您可以在输出文档中指定屏幕截图的大小,并为它们分配图形标题。自动屏幕截图的图像格式可以通过chunk选项dev指定,可能的值是pdfpngjpeg。PDF输出的默认值是PDF,其他类型的输出为png。请注意,pdf可能不像png那样可靠工作:有时HTML页面上的某些元素无法呈现为pdf截图,所以你可能想要使用dev = 'png',即使是pdf输出。这取决于HTML小部件的具体情况,在决定哪种格式更合适之前,您可以尝试pdfpng(或jpeg)。

References

Chang, Winston. 2019. Webshot: Take Screenshots of Web Pages. https://github.com/wch/webshot/.
Vaidyanathan, Ramnath, Yihui Xie, JJ Allaire, Joe Cheng, Carson Sievert, and Kenton Russell. 2020. Htmlwidgets: HTML Widgets for R. https://github.com/ramnathv/htmlwidgets.
Xie, Yihui, Joe Cheng, and Xianying Tan. 2021. DT: A Wrapper of the Javascript Library Datatables. https://github.com/rstudio/DT.