如何在shinyscreenshot截图时隐藏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
相关产品推荐
相关产品推荐

