Let's say I have the following HTML viewed in the Viewer Pane
tempDir <- tempfile() dir.create(tempDir) htmlFile <- file.path(tempDir, "index.html") write('<h1> Content</h1>', htmlFile, append = TRUE) write('<h2> Content</h2>', htmlFile, append = TRUE) write('lorem ipsum...', htmlFile, append = TRUE) viewer <- getOption("viewer") viewer(htmlFile)
When I have this html in the Viewer Pane, I can click on the "Save as image" button:
And I have the html content as a png, for example :
Is there a way to do this with the command line? I know about rstudioapi::savePlotAsImage()
, so I'm looking for a kind of saveViewerAsImage
.
Edit: I know we can do this with the {webshot} package, but I'm looking for the RStudio function that does that.
However, RStudio has a built-in method that can be accessed by clicking "Export -> Save as Image" in the viewer pane.
If you're running R through Rstudio, then the easiest way to save your image is to click on the “Export” button in the Plot panel (i.e., the area in Rstudio where all the plots have been appearing). When you do that you'll see a menu that contains the options “Save Plot as PDF” and “Save Plot as Image”.
Here's a proposal. The strategy is the following:
png
png
from the viewer to R png
A canvas
image possesses a .toDataURL()
method that returns a data URI containing the representation of the image in png
format (we also can get a jpeg
format).
The html2canvas
library can be used to take a screenshot: this library renders the current page as a canvas
image.
So, one can combine these two functions in the viewer:
html2canvas
png
using .toDataURL()
However, the html2canvas
library uses JavaScript Promise
s that are not supported by the (Windows version) RStudio viewer: a polyfill is required.
png
from the viewer to RThis task can be achieved using WebSockets.
The httpuv
package can be used to create a webserver. This server will serve a HTML
page that will be opened in the RStudio
viewer.
A WebSocket communication is established between the httpuv
server and the RStudio viewer.
From the R command line, one can send a WebSocket message to the RStudio viewer: receiving this message, the viewer takes the screenshot and send it back to the server.
I'm sorry, this code is quite long for a SO answer.
library(httpuv) # Initialize variables png <- NULL websocket <- NULL # Download Javascript libraries polyfill_promise <- readLines('https://cdn.jsdelivr.net/npm/es6-promise/dist/es6-promise.auto.min.js') html2canvas <- readLines('https://html2canvas.hertzen.com/dist/html2canvas.min.js') # Configure the httpuv server app <- list( call = function(req) { list( status = 200L, headers = list( 'Content-Type' = 'text/html' ), body = paste0(collapse = "\r\n", c("<!DOCTYPE html>", "<html>", "<head>", # polyfill the RStudio viewer to support JavaScript promises '<script type="text/javascript">', polyfill_promise, "</script>", # use html2canvas library '<script type="text/javascript">', html2canvas, "</script>", "</head>", "<body>", html_body, "</body>", '<script type="text/javascript">', # Configure the client-side websocket connection: 'var ws = new WebSocket("ws://" + location.host);', # When a websocket message is received: "ws.onmessage = function(event) {", # Take a screenshot of the HTML body element " html2canvas(document.body).then(function(canvas) {", # Transform it to png " var dataURL = canvas.toDataURL();", # Send it back to the server " ws.send(dataURL);", " });", "};", "</script>", "</html>" ) ) ) }, # Configure the server-side websocket connection onWSOpen = function(ws) { # because we need to send websocket message from the R command line: websocket <<- ws # when a websocket message is received from the client ws$onMessage(function(binary, message) { png <<- message }) } ) # From your question: html_body <- c( '<h1> Content</h1>', '<h2> Content</h2>', 'lorem ipsum...' ) # Start the server: server <- startDaemonizedServer("0.0.0.0", 9454, app) # Open the RStudio viewer: rstudioapi::viewer("http://localhost:9454") # Wait to see the result... # Send a websocket message from the command line: websocket$send("go") # send any message # Write the png image to disk: writeBin( RCurl::base64Decode( gsub("data:image/png;base64,", "", png), "raw" ), "screenshot.png" ) # Close the websocket connection websocket$close() # Stop the server stopDaemonizedServer(server)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With