How to capture html output as png in R
Asked Answered
S

2

10

I use interactive output created by networkD3 package in R. I know how to save the output as html page, but I also need to save the 'static' version of the diagram as .png file.

The code looks like this:

# Load package
library(networkD3)

# Create fake data
src <- c("A", "A", "A", "A", "B", "B", "C", "C", "D")
target <- c("B", "C", "D", "J", "E", "F", "G", "H", "I")
networkData <- data.frame(src, target)

# Plot
simpleNetwork(networkData)

I can save the output by clicking on 'Export' and then 'Save as Image'. However, I prefer to use some commands in my code to save the picture.

Slickenside answered 28/1, 2016 at 8:50 Comment(6)
Is this in a full web browser or in RStudio's window? Because if its a web browser then the RSelenium package will do it for you...Nonbelligerent
It's in RStudio viewer window. And I'd also like to run this from Jupyter Notebook eventually.Stewart
You might find this discussion helpful. github.com/ramnathv/htmlwidgets/issues/95Crossness
@JeanV.Adams I found this function thanks to you. And I was able to customize it, so it did exactly what I needed. Thank you again!Stewart
@LenkaVraná any chance you could write it up as an answer for those of us less adept with PhantomJS?Berkie
@Berkie I added my solution as an answer. However you will need to cope with PhantomJS anyway.Stewart
S
15

just an update to the possible solutions. There is a package called webshot (by W. Chang, et al.) that does this rendering and taking screenshots of html pages.

e.g usage:

webshot::webshot("file.html")

And to get the html file, you might want to check out htmlwidgets::saveWidget by R. Vaidyanathan, et al.


a fully reproducible example (saves simpleNetwork.png in your current working directory)

library(networkD3)

src <- c("A", "A", "A", "A", "B", "B", "C", "C", "D")
target <- c("B", "C", "D", "J", "E", "F", "G", "H", "I")
networkData <- data.frame(src, target)

sn <- simpleNetwork(networkData)
saveNetwork(sn, "sn.html")

library(webshot)
webshot("sn.html", "simpleNetwork.png")

enter image description here

Stannwood answered 26/1, 2018 at 6:29 Comment(0)
S
3

I used function from this page https://github.com/hafen/trelliscope/blob/master/R/thumb.R and tried to simplify it.

You need to have PhantomJS installed from http://phantomjs.org/download.html and the path set in environment variables.

The function looks like this (param p is the html widget, thumbName is the name of new .png file):

library(htmlwidgets)

widgetThumbnail <- function(p, thumbName, width = 1024, height = 768) {
  phantom <- findPhantom()

  success <- FALSE
  if(phantom == "") {
    message("** phantomjs dependency could not be found - thumbnail cannot be generated (run phantomInstall() for details)")
  } else {
    res <- try({
      ff <- paste0(thumbName, ".html")
      ffjs <- paste0(thumbName, ".js")

      # don't want any padding
      p$sizingPolicy$padding <- 0
      suppressMessages(saveWidget(p, ff, selfcontained = FALSE))

      js <- paste0("var page = require('webpage').create();
                    page.viewportSize = { width: ", width,", height: ", height," };
                    page.clipRect = { top: 0, left: 0, width: ", width,", height: ", height," };
                    page.open('", ff, "', function(status) {
                    console.log(\"Status: \" + status);
                    if(status === \"success\") {
                    page.render('", thumbName, ".png');
                    }
                    phantom.exit();
                    });")
      cat(js, file = ffjs)
      system2(phantom, ffjs)
    })
    if(!inherits(res, "try-error")) {
      success <- TRUE
    }
    if(!file.exists(paste0(thumbName, ".png"))) {
      success <- FALSE
    }
  }

  if(!success) {
    message("** could not create htmlwidget thumbnail... creating an empty thumbnail...")
  }
}

#' Get instructions on how to install phantomjs
#' @export
phantomInstall <- function() {
  message("Please visit this page to install phantomjs on your system: http://phantomjs.org/download.html")
}

# similar to webshot
findPhantom <- function() {

  phantom <- Sys.which("phantomjs")

  if(Sys.which("phantomjs") == "") {
    if(identical(.Platform$OS.type, "windows")) {
      phantom <- Sys.which(file.path(Sys.getenv("APPDATA"), "npm", "phantomjs.cmd"))
    }
  }

  phantom

}

It creates .js file, which takes your html widget, captures the screen and saves .js, .html and .png files into active directory:

# Load package
library(networkD3)

# Create fake data
src <- c("A", "A", "A", "A", "B", "B", "C", "C", "D")
target <- c("B", "C", "D", "J", "E", "F", "G", "H", "I")
networkData <- data.frame(src, target)

# Plot
plot = simpleNetwork(networkData)

# Save html as png
widgetThumbnail(p = plot, thumbName = "plot", height = 500)
Slickenside answered 27/10, 2016 at 14:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.