让动画滑块向后(从右到左)模拟倒计时?

make animated slider go backwards (right to left) to simulate a countdown?

我想为闪亮的滑块设置动画,以便在按下播放按钮时它会自动从右向左后退。我找不到办法做到这一点。滑块会模拟 10 秒的倒计时,这是我当前的代码,它走错了路。我试图弄乱步骤、最小值、最大值等,但没有成功。这有可能吗?

library(shiny); library(shinyjs); library(shinyWidgets)
jscode <- "shinyjs.play = function() {$('.slider-animate-button').trigger('click');}"
ui <- fluidPage(useShinyjs(), extendShinyjs(text = jscode),
  tags$head(tags$style(HTML('.irs-from, .irs-to, .irs-min, .irs-max, .irs-grid-text, .irs-grid-pol, .irs-slider {visibility:hidden !important;}'))),
  h3("countdown"),
  sliderInput("countdown", label = "", width = '300px',min = 0, max = 10,value = 0, step = 0.1, post="secs",
              animate = animationOptions(interval = 50, playButton = "", pauseButton = "")),
  actionButton("start", "start"))
server <- function(input, output,session) {
  disable("slider")
  observeEvent(input$start, priority=10, {js$play()})
}
shinyApp(ui, server)

感谢您的帮助..

注意:其实主要问题不在于走错了多少,而是应该开始完成,结束空着,倒计时!

您可以通过使用 shinyWidgets::sliderTextInput() 从 10 倒数到 0 并为滑块指定降序来模拟倒计时,而不是编写从右向左移动的滑块。

ui <- fluidPage(useShinyjs(), extendShinyjs(text = jscode),
         tags$head(tags$style(HTML('.irs-from, .irs-to, .irs-min, .irs-max, .irs-grid-text, .irs-grid-pol, .irs-slider {visibility:hidden !important;}'))),
         h3("countdown"),
         sliderInput("countdown", label = "", width = '300px', min = 0, max = 10, value = 0, step = 0.1, post="secs",
           animate = animationOptions(interval = 50, playButton = "", pauseButton = "")),
         shinyWidgets::sliderTextInput("countdown2", label = "", width = '300px', 
              choices = seq(from = 10, to = 0, by = -0.1), post="secs", 
              animate = animationOptions(interval = 50, playButton = "", pauseButton = "")),
         actionButton("start", "start")
      )

不确定它能达到相同的视觉效果,但这可能是一个可以接受的解决方法...

我结合两个想法得出了一个比较满意的解决方案:

  1. 来自@phalteman 的上述 由于 sliderTextInput
  2. 允许文本标签向后计数
  3. 既然我们不能让滑块从右边开始,至少我们可以让它看起来像条在减少(否则倒计时就没有意义了)。一个 CSS 技巧 使滑块看起来像是在减小,即使它仍在增加:我将滑块的颜色与背景颜色反转,所以看起来be bar实际上是逐渐消耗的空白背景(下图中的红色部分)。

css 代码改为放在 tags$head 部分:

.irs-bar {
    height: 20px !important;
    border-top: 1px solid #CCC !important;
    border-bottom: 1px solid #CCC !important;
    background: #CCC !important;
}

.irs-bar-edge {
    height: 20px !important;
    border: 1px solid #CCC !important;
    background: #CCC !important;
}

.irs-line {
    height: 20px !important;
    border: 1px solid #FF5964 !important;
    background: #FF5964 !important;
}

.irs-single {
    background: #FF5964 !important;
}

.irs-from, .irs-to, .irs-min, .irs-max, .irs-grid-text, .irs-grid-pol, .irs-slider {
    visibility:hidden !important;
}

CSS 样式表应该是这样的(我添加了一个 important 标签,因为由于某些原因没有考虑更改......?

我想到的另一种方法,使用完全不同的方法,是使用所需倒计时的 .gif 图像。

我上传了一个用 ggplot2 创建的 10 秒 gif 示例文件:https://ibb.co/tKQ4xps 该应用程序将是这样的,在停止时使用修复图像:

library(shiny)
ui <- fluidPage(h3("countdown 10secs"),
                htmlOutput("display.image"),actionButton("start", "start"),actionButton("stop", "stop"))
server <- function(input, output,session) {
  image = reactiveValues(name="full.png")
  observeEvent(input$start, {image$name="gif_timer_10sec.gif"}, ignoreInit = TRUE)
  observeEvent(input$stop, {image$name="full.png"}, ignoreInit = TRUE)
  output$display.image <- renderUI({
    HTML(paste0("<center><img height=25 width=300 align=left src=", image$name, "></center>"))})}
shinyApp(ui, server)

我还 post 生成组成 gif 的 100 张图像的基本代码:

for (i in 100:1) {
  g = ggplot() + theme(line = element_blank(),text = element_blank(),title = element_blank())
  png(paste0("plot_", 200-i, ".png"))
  g = g + geom_col(aes_string(x=1, y=i), fill="#FF5964") + xlim(0.5,1.5) + ylim(0,100) + coord_flip()
  print(g); dev.off()
}

最终的应用程序如下所示: