如何实时刷新 Shiny 中的 sliderInput()(不仅在滑动结束时)?

Posted

技术标签:

【中文标题】如何实时刷新 Shiny 中的 sliderInput()(不仅在滑动结束时)?【英文标题】:How to refresh sliderInput() in Shiny in real time (not only when the sliding ends)? 【发布时间】:2021-11-01 02:46:03 【问题描述】:

不好意思,不知道题主说的够清楚吗:在Shiny中,每次滑块滑动时,只会在滑动结束时计算更新值。如果我将它的值链接到图表,滑动时看起来不是很平滑(图表只会在鼠标松开或几秒钟后改变,而不是随着滑动而变化)。

使用滑动条改变y,图表中红点的位置会改变。

Input and Chart

我的部分代码如下:

在ui.R中:

sliderInput("slider_mean", 
html("Try to change the value of ŷ:"),
min = 1, max = 200, value = 100,),

plotlyOutput('meanplot'),

在server.R中:(这段代码可能不完整,只是举个例子)

  output$meanplot <- renderPlotly(
    
    meantb <- data.frame(y_hat = 1:200) %>%
      mutate(col2 =(y_mean1()-y_hat)^2+(y_mean2()-y_hat)^2+(y_mean3()-y_hat)^2+(y_mean4()-y_hat)^2+(y_mean5()-y_hat)^2+(y_mean6()-y_hat)^2)

    #Here is to input the slider value
    highlight_adjust <- meantb %>% 
      filter(y_hat %in% input$slider_mean)
    
    p=ggplot(meantb,
           aes(x = y_hat, y = col2)) + 
      
      geom_point(size =0.7,color="black") +
      
      geom_point(data=highlight_adjust, 
                 aes(x = y_hat, y = col2), 
                 color='red')+

      geom_line(size = 0.2,color="black") +
    ggplotly(p)
  )

Shiny 的例子:

https://shiny.rstudio.com/gallery/slider-bar-and-slider-range.html

如果我们快速移动滑块,输出值会有延迟。

【问题讨论】:

不知道有没有办法,还是闪亮的服务器限制了。我尝试给滑条加动画(模拟平滑滑动),但是虽然滑条中的动画很流畅,但是剧情还是会有延迟(如果动画速度太快,可能会拖到最后动画的,情节中的点仍在移动) 我想要达到的效果类似于在电脑上调节音量。滑动音量条时是连续变化的,而不是松开鼠标后音量变化。 我认为这是不可能的。闪亮的反应式并不是为了快速而设计的。你想要的是前端 -> 后端 -> 前端。更深一层看,就是用户交互->javascript->json数据->websocket->R json to list->R输入变化->R渲染函数->json->websocket->js。您会看到涉及多少进程,并且 js 和 R 都不是为它的速度而设计的。如果您处理来自服务器的数据,您总会有一些延迟。我的建议是纯粹在前端使用 javascript 并使用 plotly js API 来更新图表。这样你就只有 js -> plotly API。 好的,谢谢你的想法。昨天我也在考虑js,我去试试 【参考方案1】:

在阅读了一些source code of sliderInput 之后,我发现只有在HTML 代码中没有data-immediate 属性的情况下,才会遵守滑块的默认debounce 行为(参见the getRatePolicy section of this article)。

也就是说,我们只需要将这个属性添加到 HTML 中,滑块就会立即做出反应。

注意。如果您查看之前引用的源代码,您会看到receiveMessage 会将immediate 重置为false。每当我们使用updateSliderInput 时,都会调用receiveMessage。因此,在调用 updateSliderInput 之后,我们必须重新分配 immediate 数据属性才能看到行为。

在下面的示例中,您会看到被黑滑块的值会立即更新,而第二个滑块显示默认行为。单击update 会将此行为视为附带损害,如果您想使用updateSliderInput,则应确保再次添加data-immediate 属性(reset 按钮的代码显示一种可能的方法)。

但是,请注意,闪亮的团队没有向最终用户公开此功能很可能是有原因的,因此应将此解决方案视为 hack 并谨慎使用。 (从源代码来看,他们在使用updateSliderInput(因此receiveMessage)时使用immediate属性来否决默认速率策略。

library(shiny)
library(shinyjs)

my_sld <- function(...) 
   sld <- sliderInput(...)
   sld$children[[2]]$attribs$`data-immediate` <- "true"
   sld


shinyApp(
   fluidPage(
      useShinyjs(),
      my_sld("sld1", "Immediate:", 1, 10, 1), 
      verbatimTextOutput("dbg1"),
      sliderInput("sld2", "Debounced:", 1, 10, 1),
      verbatimTextOutput("dbg2"),
      actionButton("update", "Update kills Immediateness"),
      actionButton("reset", "Re-add immediate attribute")
      ),
   function(input, output, session) 
      output$dbg1 <- renderPrint(input$sld1)
      output$dbg2 <- renderPrint(input$sld2)
      observeEvent(input$update, 
         updateSliderInput(session, "sld1", value = 8)
      )
      observeEvent(input$reset, 
         runjs("$('#sld1').data('immediate', true);")
      )
   )

【讨论】:

以上是关于如何实时刷新 Shiny 中的 sliderInput()(不仅在滑动结束时)?的主要内容,如果未能解决你的问题,请参考以下文章

R Shiny:输入输入或按下操作按钮时刷新情节

如何在Shiny R中丢弃DT :: datatable上的用户编辑

更新数据表头而不刷新整个应用程序(R,Shiny) dataTableProxy()

如何连续刷新屏幕并实时更新[关闭]

如何实时自动刷新数据,反应?

您如何计算从 Shiny 中的 textInput 框中获取的数据?