R Shiny如何选择当前显示绘图并通过downloadHandler下载到文件
问题根因
你当前代码无法正常下载绘图有3个核心错误:
- 把
downloadHandler定义写在了renderPlot内部,下载处理器只会在renderPlot首次执行渲染时才会被注册,触发时机完全错误 - 没有抽离独立的绘图生成逻辑,下载时调用的
plot()是不存在的响应式对象,根本拿不到当前展示的图形 switch分支的第二个分支写法不规范,缺失分支名、变量赋值逻辑混乱,没有统一返回图形对象
修正方案
核心是把绘图生成逻辑单独封装为响应式表达式,不管是界面渲染还是下载功能,都调用这同一个响应式对象,保证两边拿到的图形完全一致。
修正后的完整可运行代码:
library(shiny) library(ggplot2) library(tidyverse) library(shinythemes) library(plotly) library(scales) library(shinyWidgets) library(shinydashboard) library(shinyjs) # 定义输入选项 type <- c("first", "second") # lambda测试数据 table <- structure(list(year = 1991:2010, lambda = c(0.68854, 0.75545, 1.63359, 1.22282, 1.70744, 1.09692, 0.51159, 1.3904, 1.09132, 0.59846, 0.43055, 0.80135, 0.69027, 0.65646, 0.95485, 1.04818, 0.67859, 1.00461, 1.16665, 1.28203)), row.names = c(NA, -20L), class = "data.frame") ui <- fluidPage( useShinyjs(), navbarPage("Test", windowTitle = "A Test", sidebarPanel( h3(""), # 选择图形类型 selectInput(inputId = "graphtype", label = "Graphic", choices = type, selected = "first"), # 初始禁用固定Y轴选项 disabled(checkboxInput("Fixed","Fixed Y axes", FALSE)) ), downloadButton('downloadPlot', 'Download Plot'), # 主面板:上方图形、下方表格 mainPanel(plotOutput("plot"), dataTableOutput("mytable")) )) server<- function (input, output, session) { session$onSessionEnded(function() { stopApp() }) # 抽离当前图形为独立响应式对象,渲染和下载统一调用 current_plot <- reactive({ xlabels <- 1991:2011 # 根据选中的图形类型返回对应ggplot对象 switch(input$graphtype, "first" = { disable("Fixed") ggplot(table,aes(year,lambda)) + geom_line(size=1.5,colour="blue") + geom_point(colour="orange",size=4) + scale_x_continuous("",breaks = xlabels) + theme(axis.text.x = element_text(angle = 45, vjust = 0.5)) + labs(x="",y="test",title= "Population growth rate of Fish ") }, "second" = { enable("Fixed") line_color <- ifelse(input$Fixed == FALSE, "red", "yellow") ggplot(table,aes(year,lambda)) + geom_line(size=1.5,colour=line_color) + geom_point(colour="green",size=4) + scale_x_continuous("",breaks = xlabels) + theme(axis.text.x = element_text(angle = 45, vjust = 0.5)) + labs(x="",y="fish test",title= "Population growth") } ) }) # 渲染主面板图形 output$plot <- renderPlot({ current_plot() }) # 下载处理器,和renderPlot平级定义 output$downloadPlot <- downloadHandler( filename = "plot.png", content = function(file) { ggsave(current_plot(), filename = file, dpi = 300, width = 10, height = 6) } ) } shinyApp(ui = ui, server = server)
关键改动说明
- 所有图形生成逻辑统一放在
current_plot()响应式中,切换图形类型、勾选固定Y轴时都会自动更新,界面展示和下载拿到的是完全相同的对象,不会出现下载内容和显示不一致的问题 - 修正了原
switch语句缺失"second"分支名的错误,简化了重复的ggplot代码 - 将
downloadHandler移到renderPlot外部,应用启动时就会正常注册下载功能,不会出现下载按钮无响应的问题 - 给
ggsave补充了分辨率、宽高参数,可以根据需要自行调整导出图片的尺寸和清晰度
内容的提问来源于stack exchange,提问作者Salvador
相关产品推荐
相关产品推荐

