Closed robertleitner closed 8 years ago
Hmm, plotly_IMAGE()
should work...does plotly_POST()
work for you? If not, you probably haven't set your credentials properly. You can use plotly:::verify("username")
and plotly:::verify("api_key")
to double-check the R package can find them.
You can also open the interactive viz in a web browser and use plotly's "download as plot png" button (this isn't yet working in RStudio, but we're working on it)
Here is a SO related post: exporting png files from plotly in r without internet connection
The idea is to create it without UI interaction and with no internet connection.
plotly_POST()
works, but need internet. I believe that with the new Open JS Strategy that this functionality make sense.
tks
You could use something like RSelenium to automate this, but I won't be adding any native support to plotly's R package.
does plotly_IMAGE only work with username and api_key?
@xzmagic unfortunately yes. The conversion is created in Plotly server, not locally.
@timelyportfolio bootstrapping off of discusion in https://github.com/plotly/plotly.js/issues/83, what do you think about using https://github.com/jeroenooms/rsvg to produce bitmaps locally?
(of course I'd prefer avoiding an extra R dependency if a pure JS solution seems plausible)
Funny, I had the same idea this morning :) I started yesterday on very preliminary work to attach the toImage
method to a plot. I think we could tie this in. However, until the nested svgs are eliminated, RStudio will still render them incorrectly. Perhaps I could demonstrate a method in a Gist of how we could do what you are saying with rsvg
. Would that work?
Remember though also the newest knitr
+ webshot
will handle a lot of these cases automatically.
That'd be great!
Here are two ways of accomplishing a static image of a Plotly graph. If using in rmarkdown
, I highly recommend using the newest knitr
to automatically convert htmlwidgets
(see knitr News).
# In issue 311
# there was some discussion how we might
# get our plotly graph as a static image.
# Below are two ways to accomplish this:
# 1. Use webshot or do automatically with knitr
# If you want more info about the auto-knitr
# method, then please see
# https://github.com/yihui/knitr/blame/c3085229f5a02506e40f21c1cecf6d8448f5caaa/NEWS.md#L7-L10
#
# 2. Use Shiny gadgets and rsvg
#
Method #2 has the advantage of multiple export formats.
######## Webshot ##################################
library(plotly)
# devtools::install_github("wch/webshot")
library(webshot)
library(htmltools)
library(magrittr)
# make a simple plotly graph to illustrate
ggp <- ggplotly(
ggplot(cars, aes(speed,dist)) + geom_point(),
height=400,
width=400
)
png_webshot <- tempfile(fileext = ".png")
tagList(
htmlwidgets:::as.tags.htmlwidget(as.widget(
ggp
))
) %>%
html_print %>%
# get forward slash on windows
normalizePath(.,winslash="/") %>%
# replace drive:/ with drive:// so C:/ becomes C://
gsub(x=.,pattern = ":/",replacement="://") %>%
# appends file:/// to make valid uri
paste0("file:///",.) %>%
# screenshot it for lots of good reasons
webshot( file = png_webshot, delay = 1 )
# see our new png in your image viewer of choice
system(sprintf("open %s", shQuote(png_webshot)))
rsvg
######## Shiny gadgets and rsvg ###################
library(plotly)
library(rsvg)
library(shiny)
library(miniUI)
library(htmlwidgets)
library(htmltools)
# make a little Shiny miniUI gadget
# borrowed some code from chemdoodle
# https://github.com/zachcp/chemdoodle/blob/master/R/chemdoodle_sketcher_gadgets.R
plotly_gadget <- function(plotly_widget, height=NULL, width=NULL){
ui <- miniPage(
miniContentPanel(
htmlwidgets:::as.tags.htmlwidget(as.widget(plotly_widget))
),
gadgetTitleBar("Get Static Image...", right = miniTitleBarButton("done", "Done", primary = TRUE)),
tags$script('
document.getElementById("done").onclick = function() {
var plotly_svg = Plotly.Snapshot.toSVG(
document.querySelectorAll(".plotly")[0]
);
Shiny.onInputChange("plotly_svg", plotly_svg);
};
')
)
server <- function(input, output, session) {
observeEvent(input$done, { stopApp(input$plotly_svg) })
}
runGadget(ui,
server,
viewer = dialogViewer("PlotlyStaticImage",
width = width,
height = height))
}
# make a simple plotly graph to illustrate
ggp <- ggplotly(
ggplot(cars, aes(speed,dist)) + geom_point(),
height=400,
width=400
)
# run our gadget to get the svg
svg <- plotly_gadget(ggp)
# use rsvg to convert our svg to png
# feel free to do something other than png
png_gadget <- tempfile(fileext=".png")
rsvg_png(charToRaw(svg), png_gadget)
# see our new png in your image viewer of choice
system(sprintf("open %s", shQuote(png_gadget)))
Thanks @timelyportfolio. I think for now we'll just leave this be and hope plotly.js provides a solution. For the record, I think I prefer the webshot approach, but I don't want to depend on it.
Quick PSA 🎤
plotly.js
now has an officially supported API for offline image export:
https://plot.ly/javascript/static-image-export/
🎉
@yankev is is adding programmatic offline export support to the Python client in this PR: https://github.com/plotly/plotly.py/pull/494
@spencerlyon2 has added incredible offline image export for the Julia client described here: http://spencerlyon.com/PlotlyJS.jl/manipulating_plots/#saving-figures
I will try to add this in over next couple of days.
@timelyportfolio can we get away with export without a full-blown DOM renderer?
I've added this function to the major update I've been working on locally (I'll start the pull request tomorrow probably). What do you think?
#' Export a plotly graph to a static file
#'
#' @param p a plotly or ggplot object.
#' @param file a filename. See the file argument of \code{webshot::webshot}
#' for valid extensions.
#' @param ... arguments passed onto \code{webshot::webshot}
#' @export
#' @examples \dontrun{
#' export(plot_ly(economics, x = ~date, y = ~pce))
#' }
export <- function(p, file = "plotly.png", ...) {
if (system.file(package = "webshot") == "") {
stop(
'Please install the webshot package ',
'(if not on CRAN, try devtools::install_github("wch/webshot"))'
)
}
f <- basename(tempfile('plotly', '.', '.html'))
on.exit(unlink(f), add = TRUE)
html <- htmlwidgets::saveWidget(plotly_build(p), f)
webshot::webshot(f, file, ...)
}
I don't see any way possible to export without a full-blown DOM renderer.
Excited to see your changes.
Closed via d2bf2a1eb56d824a091e2cc9afea09a5968dd050.
How can I save an interactive plot generated by plotly locally as png? The commands png()...dev.off() won't capture the plot command and the function call plotly_IMAGE throws an authorization error although the plot is generated locally and I'm logged in.
Thanks for your help.