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

如何在shinyscreenshot截图时隐藏radioGroupButtons?

问题:Shiny截图时radioGroupButtons无法隐藏

我使用shinyscreenshot开发Shiny应用,应用包含一张“评分”卡片,其中的radioGroupButtons在应用界面中不可见,但使用shinyscreenshot截图时会显示出来并与数值重叠,导致截图混乱。尝试用shinyjs切换按钮可见性未达到预期效果,求解决办法。

最小可复现代码

library(shiny)
library(bs4Dash)
library(shinyWidgets)
library(shinyjs)
library(shinyscreenshot)

my_ids <- c("region_1", "region_2") 
my_labels <- c("A", "B") 

ui <- bs4DashPage(
  title = "My Example",
  header = bs4DashNavbar(),
  sidebar = bs4DashSidebar(disable = TRUE),  
  body = bs4DashBody(
    useShinyjs(),
    
    # CSS for radio button styles and hiding elements
    tags$style(HTML("
      .btn-zero {background-color: white; color: black;}
      .btn-zero.active {background-color: #a2ff45; color: black;}
      .btn-one {background-color: white; color: black;}
      .btn-one.active {background-color: #a2ff45; color: black;}
      .btn-two {background-color: white; color: black;}
      .btn-two.active {background-color: #a2ff45; color: black;}
      .btn-three {background-color: white; color: black;}
      .btn-three.active {background-color: #a2ff45; color: black;}
      .region-label { line-height: 2.5; }

      /* Hide elements during screenshot */
      .hide-for-screenshot { display: none !important; }
    ")),
    
    bs4Card(
      title = "My Score",
      width = 6,
      style = "height: 200px; overflow: auto;",  
      tags$style(HTML("
        .region-label { margin-top: -10px; }
      ")),
      # Render radio buttons for each region
      lapply(seq_along(my_ids), function(i) {
        fluidRow(
          column(6, h4(class = "region-label", paste(i-1, my_labels[i]))),
          column(6, div(
            style = "display: inline-block;",
            shinyWidgets::radioGroupButtons(
              inputId = my_ids[i],
              label = NULL,
              choices = 0:3,
              selected = 0,
              checkIcon = list(yes = icon("check")),
              status = c("zero", "one", "two", "three"),
              size = 'xs'
            )
          ))
        )
      })
    ),
    
    # Screenshot Button
    actionButton("take_screenshot", "Take Screenshot", style = "margin-top: 10px;")
  )
)

server <- function(input, output, session) {
  observeEvent(input$take_screenshot, {
    # Temporarily hide radio buttons
    shinyjs::addClass(selector = ".radioGroupButtons", class = "hide-for-screenshot")
    
    # Take screenshot and remove the hide class afterward
    shinyscreenshot::screenshot()
    
    # Show radio buttons again
    shinyjs::removeClass(selector = ".radioGroupButtons", class = "hide-for-screenshot")
  })
}

shinyApp(ui, server)

已尝试方案

  • 自定义CSS:添加带display: none !important;的.hide-for-screenshot类,截图前应用、截图后移除
  • 使用shinyjs:通过addClass和removeClass为radioGroupButtons切换隐藏类

问题核心

shinyscreenshot::screenshot()是异步操作,原代码中触发截图后立刻执行removeClass,导致截图还未完成时,radio按钮的样式已经被恢复,因此截图中仍会显示按钮。

解决方案

方法1:延迟恢复样式

修改server中的observeEvent,在截图后延迟一段时间再移除隐藏类,确保截图完成:

server <- function(input, output, session) {
  observeEvent(input$take_screenshot, {
    # 临时隐藏radio按钮
    shinyjs::addClass(selector = ".radioGroupButtons", class = "hide-for-screenshot")
    
    # 触发截图
    shinyscreenshot::screenshot()
    
    # 延迟恢复按钮显示,时间可根据实际情况调整(如500ms)
    shinyjs::delay(500, {
      shinyjs::removeClass(selector = ".radioGroupButtons", class = "hide-for-screenshot")
    })
  })
}

方法2:使用精确选择器(避免冲突)

为radioGroupButtons添加自定义类,确保选择器准确:
在UI的radioGroupButtons中添加class = "score-radio-buttons":

shinyWidgets::radioGroupButtons(
  inputId = my_ids[i],
  label = NULL,
  choices = 0:3,
  selected = 0,
  checkIcon = list(yes = icon("check")),
  status = c("zero", "one", "two", "three"),
  size = 'xs',
  class = "score-radio-buttons"  # 自定义类
)

然后修改server中的选择器:

shinyjs::addClass(selector = ".score-radio-buttons", class = "hide-for-screenshot")
# ...
shinyjs::removeClass(selector = ".score-radio-buttons", class = "hide-for-screenshot")

方法3:JS直接控制样式(更可靠)

使用shinyjs::runjs直接操作DOM,确保样式生效后再截图:

server <- function(input, output, session) {
  observeEvent(input$take_screenshot, {
    shinyjs::runjs('
      // 获取所有radio按钮容器
      const radioBtns = document.querySelectorAll(".radioGroupButtons");
      // 保存原始显示状态
      const originalDisplays = Array.from(radioBtns).map(btn => btn.style.display);
      
      // 隐藏按钮
      radioBtns.forEach(btn => btn.style.display = "none");
      
      // 截图完成后恢复状态
      setTimeout(() => {
        radioBtns.forEach((btn, idx) => btn.style.display = originalDisplays[idx]);
      }, 600);
    ')
    
    // 延迟截图,确保样式生效
    shinyjs::delay(100, shinyscreenshot::screenshot())
  })
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 08:30:59