如何为Shiny应用添加截图(PNG/JPG)或PDF导出功能?
Shiny应用可视化区域导出方案
一、单个可视化区域导出(最优,对应绿色标记区域)
Shiny原生支持针对plotOutput生成的图表直接添加下载功能,只需在UI中加入下载按钮,配合server端的downloadHandler即可实现。以下是修改后的完整代码:
修改后代码
library(shiny) library(shinydashboard) library(data.table) library(DT) library(bslib) server = shinyServer(function(input,output){ output$histogram = renderPlot( hist(faithful$eruptions, breaks=input$days_plot) ) output$histogram2 = renderPlot( hist(faithful$eruptions, breaks=input$days_plot) ) output$active_cases = DT::renderDataTable( mtcars, selection = 'single', options=list(scrollX=TRUE)) # 第一个图表的下载处理器 output$download_hist1 <- downloadHandler( filename = function() { paste0("histogram_", Sys.Date(), ".png") }, content = function(file) { png(file, width = 800, height = 600) hist(faithful$eruptions, breaks=input$days_plot) dev.off() } ) # 第二个图表的下载处理器 output$download_hist2 <- downloadHandler( filename = function() { paste0("histogram2_", Sys.Date(), ".png") }, content = function(file) { png(file, width = 800, height = 600) hist(faithful$eruptions, breaks=input$days_plot) dev.off() } ) }) ui = shinyUI( dashboardPage( dashboardHeader( title="just a test" ), dashboardSidebar( sidebarMenu(id="tabs", menuItem("Tab1", tabName="active_cases", icon = icon("magnifying-glass-location")), menuItem("Tab2", tabName="archive", icon = icon("box-archive")), menuItem("Configuration", sliderInput("days_plot", "Days into past", 1, 60, 30)) ) ), dashboardBody( tabItems( tabItem(tabName="active_cases", shiny::h2("Active Cases"), fluidRow( box(title="Table", status="primary", solidHeader=TRUE, div(DT::dataTableOutput("active_cases"))) ), fluidRow( box(title="Visual1", status="primary", solidHeader=TRUE, plotOutput("histogram"), # 添加下载按钮 downloadButton("download_hist1", "下载该图表")), box(title="Visual2", status="primary", solidHeader=TRUE, plotOutput("histogram2"), downloadButton("download_hist2", "下载该图表")) ) ), tabItem(tabName="archive", shiny::h2("Archive")) ) ) ) ) shinyApp(ui, server)
关键说明:
- 每个
plotOutput对应一组downloadButton和downloadHandler,点击按钮即可导出当前图表为PNG格式;若需JPG,将代码中的png()替换为jpeg()即可。 - 可通过调整
png()的width和height参数控制导出图片的尺寸。
二、多区域/整页导出(对应黄色标记区域或整页)
如果需要导出多个可视化区域(比如两个图表所在的行)或整页,可使用webshot2包,它能通过CSS选择器定位页面元素并导出为图片或PDF。
步骤1:安装依赖
install.packages("webshot2") webshot2::install_chromium() # 需安装Chromium环境支持
步骤2:修改代码实现多区域/整页导出
library(shiny) library(shinydashboard) library(data.table) library(DT) library(bslib) library(webshot2) server = shinyServer(function(input,output){ output$histogram = renderPlot( hist(faithful$eruptions, breaks=input$days_plot) ) output$histogram2 = renderPlot( hist(faithful$eruptions, breaks=input$days_plot) ) output$active_cases = DT::renderDataTable( mtcars, selection = 'single', options=list(scrollX=TRUE)) # 导出两个图表所在的行 output$download_plots_row <- downloadHandler( filename = function() { paste0("plots_row_", Sys.Date(), ".png") }, content = function(file) { # 通过ID定位目标行(比nth-child更可靠) webshot2::webshot( url = session$clientData$url_local, file = file, selector = "#plots_row", vwidth = 1200, vheight = 600 ) } ) # 导出整页为PDF output$download_full_page <- downloadHandler( filename = function() { paste0("full_page_", Sys.Date(), ".pdf") }, content = function(file) { webshot2::webshot( url = session$clientData$url_local, file = file, vwidth = 1200, vheight = 800, expand = c(10, 10, 10, 10) ) } ) }) ui = shinyUI( dashboardPage( dashboardHeader( title="just a test" ), dashboardSidebar( sidebarMenu(id="tabs", menuItem("Tab1", tabName="active_cases", icon = icon("magnifying-glass-location")), menuItem("Tab2", tabName="archive", icon = icon("box-archive")), menuItem("Configuration", sliderInput("days_plot", "Days into past", 1, 60, 30)) ) ), dashboardBody( tabItems( tabItem(tabName="active_cases", shiny::h2("Active Cases"), fluidRow( box(title="Table", status="primary", solidHeader=TRUE, div(DT::dataTableOutput("active_cases"))) ), # 给目标行添加ID,方便精准定位 fluidRow(id="plots_row", box(title="Visual1", status="primary", solidHeader=TRUE, plotOutput("histogram")), box(title="Visual2", status="primary", solidHeader=TRUE, plotOutput("histogram2")) ), # 添加多区域和整页下载按钮 fluidRow( box(width=6, downloadButton("download_plots_row", "下载两个图表区域")), box(width=6, downloadButton("download_full_page", "下载整页为PDF")) ) ), tabItem(tabName="archive", shiny::h2("Archive")) ) ) ) ) shinyApp(ui, server)
关键说明:
- 给目标元素添加
id(如id="plots_row"),可通过selector="#plots_row"精准定位导出区域。 - 导出格式支持PNG、JPG、PDF,只需修改
filename的后缀即可。
内容的提问来源于stack exchange,提问作者Marco_CH
相关产品推荐
相关产品推荐

