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

如何在Shiny截图前后触发元素显隐事件?

解决Shiny截图前后隐藏/显示元素的问题

问题描述

使用shinyscreenshot包对Shiny应用截图时,需要先隐藏id="options_results"的元素、显示id="flag_options"元素,截图完成后再恢复原状态。但直接按顺序执行hide/show和screenshot()无法生效,因为截图操作是异步的,DOM还没完成更新就已执行截图。

解决方案

核心是处理截图的异步特性:shinyscreenshot::screenshot()不会等待DOM更新完成就执行,因此需要延迟截图操作确保元素状态生效,同时在截图完成后再恢复元素显示状态。

修改后的完整代码

library(shiny)
library(shinyjs)
library(shinyscreenshot)

ui <- fluidPage(
  useShinyjs(),
  shinyjs::hidden(div(id = "flag_options", h2("This should be"), div(uiOutput("flag_reactive")))),
  
  div(id = "options_results", 
      selectInput("choice_country", "Select Country", choices = c("US", "FR")),
      h2("This should not be in the screenshot")),
  
  actionButton("go_down", "Download")
)


server <- function(input, output) {
  
  output$flag_reactive <- renderUI({
    tags$img(
      src = paste0("https://cdn.rawgit.com/lipis/flag-icon-css/master/flags/4x3/", tolower(input$choice_country), ".svg"),
      style = "width: 20%;"
    )
  })
  
  observeEvent(input$go_down, {
    # 切换元素显示状态
    hide("options_results", anim = FALSE)
    show("flag_options", anim = FALSE)
    
    # 延迟执行截图,确保DOM更新完成
    delay(
      ms = 500, # 可根据实际情况调整延迟时长
      expr = {
        screenshot(
          # 截图完成后向Shiny发送信号,触发状态恢复
          callback = 'Shiny.setInputValue("screenshot_done", true);'
        )
      }
    )
  })
  
  # 监听截图完成信号,恢复元素初始状态
  observeEvent(input$screenshot_done, {
    show("options_results", anim = FALSE)
    hide("flag_options", anim = FALSE)
  })
}

shinyApp(ui = ui, server = server)

关键说明

  • 用shinyjs::delay()给DOM预留更新时间,避免截图时元素状态还未切换完成。
  • 通过screenshot()的callback参数,在截图完成后触发元素状态恢复,比固定延迟恢复更可靠(适配不同浏览器的截图耗时差异)。

内容的提问来源于stack exchange,提问作者Bambs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 10:38:10