Omar Abd El-Naser
Omar Abd El-Naser

Reputation: 704

Saving interactive graphs through viewer (export) as (PNG)

I want to save my interactive graph as a png, i can do it through viewer and export it as png but i've thousands of them and must take them automatically.

There's a way which is using webshot package, but i tried this approach and it takes alot of time, because i want to save them at the same time, for example : i've 4000 html graphs generated using R and must save them as image in time interval 1 min, when i use webshot, it takes arround 43 mins because system2takes alot of time .

so i want to export them using function which viewer pane use, here's an image explain what i want .

enter image description here

Here's code as an example for interactive graph, that doesn't mean my graphs r leaflet class, i provide it as an example.

library(leaflet)

m <- leaflet() %>%
  addTiles() %>%  # Add default OpenStreetMap map tiles
  addMarkers(lng=174.768, lat=-36.852, popup="The birthplace of R")

and here's what i'm thinking of :

function(m,"SaveAs.png")

Please i need help, i searched a lot and spent a lot of time trying to find a solution.


according to this question How to save Leaflet in R map as png or jpg file?

It differs from my question , i need generic function for any interactive graphs , there's functions for plotly but it's only for plotly graphs,Also the question usion webshot function which using PhantomJs and i mentioned above that PhantomJS is tooooo slow also Selenium also wkhtmltoimage, i tried lots of things.

Please notice that i need generic function or at least the function that viewer is using

Upvotes: 1

Views: 3636

Answers (1)

hrbrmstr
hrbrmstr

Reputation: 78792

The only way to capture a bitmap of htmlwidgets (like leaflet) is to load them in a browser context, capture a bit (or all) of the viewport and write that out to a file. That's an ugly round-trip process in a heavyweight browser context, marshalling data between internal DOM representations to HAR (behind the scenes) — which encodes binary bit into base64, to the browser context broker/driver, to R, them from base64 to memory or a file.

There is an additional issue where many HTML widgets saved to a file will not always load in a static file context (i.e you need a running web server). I have no idea if that's true for googleway saved widgets but it is often true for leaflet.

For the following, you'll need to:

  • figure out how to install devd binary
  • figure out how to install selenium with the chrome driver (safari driver may be faster as its js engine is faster)
  • start selenium w/chrome driver

Toy example setup to save out 5 widgets:

library(seleniumPipes)
library(leaflet)
library(purrr)
library(devd) # install_github("hrbrmstr/devd")

m <- leaflet() %>%
  addTiles() %>%
  addMarkers(lng=174.768, lat=-36.852, popup="The birthplace of R")

dir.create("/tmp/pages", showWarnings = FALSE)
dir.create("/tmp/pngs", showWarnings = FALSE)

walk(1:5, ~saveWidget(m, file.path("/tmp/pages", sprintf("%x.html", .x))))

Start a selenium session and also start up a web server:

remDr <- remoteDr(browserName = "chrome", port = 4444L)

proc <- devd_start("/tmp/pages", open_browser = FALSE)

Walk through the files and take screenshots:

list.files("/tmp/pages", "*.html$", full.names = FALSE) %>% 
  walk(~{
    print(system.time({
      page_url <- sprintf("http://devd.io:8000/%s", .x)
      out_file <- sprintf("/tmp/pngs/%s.png", .x)
      remDr %>% 
        go(page_url) %>% 
        takeScreenshot(file=out_file)
    }))
  })

You get:

##  user  system elapsed 
## 0.473   0.082   6.561 
## 0.449   0.083   4.110 
## 0.447   0.073   4.429 
## 0.419   0.068   3.568 
## 0.423   0.085   4.493 

for that sequence.

It doesn't get much better if we try to just capture the pngs & turn off some takeScreenshot() features, either:

list.files("/tmp/pages", "*.html$", full.names = FALSE) %>% 
  map(~{
    print(system.time({
      page_url <- sprintf("http://devd.io:8000/%s", .x)
      out_file <- sprintf("/tmp/pngs/%s.png", .x)
      remDr %>% 
        go(page_url) %>% 
        takeScreenshot(display=FALSE, useViewer=FALSE, returnPNG=TRUE)
    }))
  }) -> pngs

##  user  system elapsed 
## 0.448   0.060   4.801 
## 0.440   0.058   4.894 
## 0.463   0.074   4.857 
## 0.466   0.068   5.010 

Don't forget to top the web server:

devd_stop(proc)

It is possible to speed this up by doing things in parallel, but others way be more willing to give you free consulting than I am, especially since you weren't and still aren't exactly forthcoming in your question details. The answer is mostly for others with a similar need but less entitlement.

Upvotes: 3

Related Questions