You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shiny中通过downloadHandler导出dygraph图表至PDF失败求助

Shiny中导出dygraph与ggplot混合PDF的解决方案

问题根源

gridExtra::grid.arrange 仅支持处理基于grid绘图系统的静态图形对象(如ggplot2、base R生成的静态图),dygraph属于交互式HTML组件,不属于grid可识别的图形类型,无法直接传入进行排版导出。

解决方案核心逻辑

先将dygraph渲染为静态图片,再转换为grid可识别的对象,即可与ggplot对象合并排版导出为PDF。

依赖安装

先安装所需依赖包:

install.packages(c("ggplot2", "webshot2", "magick", "grid"))

完整可运行修改代码

library(shiny)
library(dygraphs)
library(htmltools)
library(gridExtra)
library(ggplot2)
library(webshot2)
library(magick)
library(grid)

ui <- navbarPage(
  tabPanel(title = "Download",
           downloadButton("downloadcharts1"),
           downloadButton("downloadcharts2"),
           downloadButton("downloadcharts")
  )   
)


server <- function(input, output, session){
  
  vals <- reactiveValues(p1=NULL, p2=NULL)
  
  temperature <- ts(frequency = 12, start = c(1980, 1),
                    data = c(7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 
                             25.2, 26.5, 23.3, 18.3, 13.9, 9.6))
  rainfall <- ts(frequency = 12, start = c(1980, 1),
                 data = c(49.9, 71.5, 106.4, 129.2, 144.0, 176.0, 
                          135.6, 148.5, 216.4, 194.1, 95.6, 54.4))
  data <- as.data.frame(cbind(temperature, rainfall))
  g <- ggplot(data = data, aes(x=temperature, y=rainfall)) + geom_point()
  
  vals$p1 <- g

  # create a list of dygraphs objects
  dy_graph <- list(
    dygraphs::dygraph(temperature, group="temp_rain", main="temperature"),
    dygraphs::dygraph(rainfall, group="temp_rain", main="rainfall")
  )
  dy_graph<- htmltools::browsable(htmltools::tagList(dy_graph))
  vals$p2 <- dy_graph 


  output$downloadcharts1 <- downloadHandler(
    filename = function(){"chart1.pdf"},
    content = function(file){
      pdf(file, onefile=TRUE)
      grid.arrange(vals$p1)
      dev.off()
    }
  )

  output$downloadcharts2 <- downloadHandler(
    filename = function(){"chart2.pdf"},
    content = function(file){
      # 创建临时文件存储中间产物
      tmp_html <- tempfile(fileext = ".html")
      tmp_png <- tempfile(fileext = ".png")
      # 保存dygraph为静态HTML
      save_html(vals$p2, tmp_html)
      # HTML转静态PNG,zoom参数控制导出清晰度,数值越大越清晰
      webshot(tmp_html, file = tmp_png, zoom = 2)
      # PNG转grid可识别的grob对象
      dy_grob <- rasterGrob(image_read(tmp_png))
      # 导出PDF
      pdf(file, onefile=TRUE)
      grid.arrange(dy_grob)
      dev.off()
      # 清理临时文件
      unlink(c(tmp_html, tmp_png))
    }
  )


  output$downloadcharts <- downloadHandler(
    filename = function(){"charts1&2.pdf"},
    content = function(file){
      tmp_html <- tempfile(fileext = ".html")
      tmp_png <- tempfile(fileext = ".png")
      save_html(vals$p2, tmp_html)
      webshot(tmp_html, file = tmp_png, zoom = 2)
      dy_grob <- rasterGrob(image_read(tmp_png))
      pdf(file, onefile=TRUE)
      # 按两行排版两个图表,可自行调整ncol/nrow参数修改布局
      grid.arrange(vals$p1, dy_grob, nrow = 2)
      dev.off()
      unlink(c(tmp_html, tmp_png))
    }
  )

}

runApp(list(ui=ui, server=server), launch.browser=TRUE)

内容的提问来源于stack exchange,提问作者K.RAC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 13:21:02