如何保存闪亮图的 png 图像,使其与我屏幕上的尺寸相匹配?

How to save png image of Shiny plot so it matches the dimensions on my screen?

我用 shiny 绘制了一张图像,并创建了一个保存按钮将图像保存为 .png 文件。

server <- function(input, output) {

  output$plot <- renderPlot({
    plot(1:500,rep(1:5,100))
  })

  plotInput <- function(){
    plot(1:500,rep(1:5,100))
  }

  output$savePlot <- downloadHandler(
    filename = "file.png", 
    content = function(file) {
      png(file)
      plotInput()
      dev.off()
    }
  )
}

当我在我的笔记本电脑屏幕(1366x768 分辨率)上的 Shiny 应用程序中查看图像时,绘图被拉长了(即长于宽度)。 [注:这就是我想要的]。

当我保存绘图时,输出文件不再像在应用程序本身中查看时那样水平长,而是保存为正方形。

现在我知道我可以使用 png() 函数中的 widthheightunits 参数修改输出图像的大小。

但是,我不知道我在 Shiny 应用程序中打开的图像的大小。

所以我的问题是:

有没有办法在 Shiny 应用程序中保存图像,使其自动具有与在屏幕上查看时相同的 "dimensions"?

注意:我意识到当我将我的应用程序移动到新的显示器或设备时,图表的 shape/dimensions 会发生变化,因此我正在寻找一些方法来主动确定图像的当前尺寸.


这是我的情节在 我笔记本电脑屏幕上的 Shiny 应用程序中的样子:


同样,我希望解决方案能够自动确定屏幕上显示的绘图的当前尺寸,并将这些尺寸应用于我保存的 png 输出图像。

将以下 javascript 添加到您的 UI 中:

 tags$script("$(document).on('shiny:connected', function(event) {
var myWidth = $(window).width();
Shiny.onInputChange('shiny_width',myWidth)

});"),

  tags$script("$(document).on('shiny:connected', function(event) {
var myHeight = $(window).height();
Shiny.onInputChange('shiny_height',myHeight)

});")

然后,按如下方式更改 downloadHandler 代码:

  output$savePlot <- downloadHandler(
    filename = "file.png", 
    content = function(file) {
      png(file,
          width = input$shiny_width,
          height = input$shiny_height)
      plotInput()
      dev.off()
    }
  )

您可以使用图像 URI 保存图像。 在这种情况下,图像与您在 shiny 中看到的图像完全相同。 此外,您不需要在 downloadHandler 中重新绘制。 有关详细信息,请查看我在此线程中的回答:

在此处重新发布示例代码:

library(shiny)
library(magick)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(),
  #visibale action button - this button simulates click on hidden download button 
  actionButton("save_myPlot", "Download", icon = icon("download")),
  #hidden download button
  downloadButton("save_myPlot_hidden", style = "visibility: hidden;"),
  # plot
  plotOutput("myPlot")
)

server <- function(input, output, session) {
  
  #get the plot image URI and simulate click on download button
  observeEvent(input$save_myPlot, {
    shinyjs::runjs(
      "
       var p_src = document.getElementById('myPlot').childNodes[0].src; 
       Shiny.setInputValue('plot_src', p_src);
       document.getElementById('save_myPlot_hidden').click();
      "
    )
  })
  
  # downaload handler - save the image
  output$save_myPlot_hidden <- downloadHandler(
    filename = function() { 
      paste0("plot_", Sys.Date(), ".png") },
    content = function(file) {
      # get image code from URI
      plot_src <- gsub("^data.*base64,", "", input$plot_src)
      # decode the image code into the image
      plot_image <- image_read(base64_decode(plot_src))
      # save the image
      image_write(plot_image, file)
    })
  
  # plot
  output$myPlot <- renderPlot(
    plot(rnorm(5), rnorm(5))
  )
}

shinyApp(ui = ui, server = server)