如何在更改第二个sliderInput时重置一个sliderInput而不会触发Shiny

时间:2019-02-03 20:20:16

标签: r shiny reactive-programming

如果这个问题的答案很简单,我很抱歉,而我对Shiny的有限了解导致我在广泛寻找答案时走错了路。

我正在尝试解决以下问题。我有一个依赖于两个sliderInputs来创建绘图的输出。在每次第一个滑块的值更改时应重置第二个滑块的状态的意义上,这些滑块又相互依赖。我当前为实现此目的的尝试如下:

library(shiny)
library(plotly)
library(ggplot2)    

ui <- fluidPage(

  titlePanel("Test"),
  sidebarLayout(
    sidebarPanel(
      sliderInput("slider1", "Slider1:", min = 0, max = 100, value = 0, step= 0.1),
      sliderInput("slider2", "Slider2:", min = 0, max = 100, value = 0, step= 0.1)
    ),
    mainPanel(
      plotlyOutput('plot', height = 600)
    )
  )
)


server <- function(input, output, session) {

  #temporary state storage.
  slider1.state <- reactiveVal(-1)
  counter <- reactiveVal(0)

  output$plot <- renderPlotly({

    print(paste("Function Call Number ", isolate(counter()) )) 
    counter(isolate(counter())+1)

    #Only reset Slider2 if Slider1 has been changed
    if (isolate(slider1.state()) != input$slider1) {

      #this triggers a redraw
      updateSliderInput(session, "slider2", value=0 )

    }
    ylim_max = input$slider2

    #set the new values of the sliders
    slider1.state(input$slider1)

    ggplot(data.frame()) + geom_point() + xlim(0, input$slider1) + ylim(0, ylim_max)

  })

}

shinyApp(ui, server)

我正在使用反应性值来存储slider1的状态,并且仅在slider2更改时才使用updateSliderInput重置slider1。但是,我面临的问题是,对updateSliderInput的调用第二次触发了renderPlotly函数,因此不必要地计算和重绘了第二次的绘图。

我试图找到一种解决方案,该解决方案可以使我在不触发事件的情况下以某种方式更新sliderInput,但无济于事。是否有一种优雅的方式来获得这种行为?理想情况下,我正在寻找一种可以应用于任意输入的解决方案。

在此问题上的任何帮助将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:0)

您可以使用debounce()来避免不必要的更新:

library(shiny)
library(plotly)
library(ggplot2)    

ui <- fluidPage(

  titlePanel("Test"),
  sidebarLayout(
    sidebarPanel(
      sliderInput("slider1", "Slider1:", min = 0, max = 100, value = 0, step= 0.1),
      sliderInput("slider2", "Slider2:", min = 0, max = 100, value = 0, step= 0.1)
    ),
    mainPanel(
      plotlyOutput('plot', height = 600)
    )
  )
)


server <- function(input, output, session) {

  observeEvent(input$slider1, {
    updateSliderInput(session, "slider2", value=0 )
  })

  plot_limits <- reactive({
    list(xlim_max = input$slider1, ylim_max = input$slider2)
  })

  plot_limits_d <- plot_limits %>% debounce(500)

  counter <- reactiveVal(0)

  output$plot <- renderPlotly({
    print(paste("Function Call Number ", isolate(counter()) )) 
    counter(isolate(counter())+1)
    ggplot(data.frame()) + geom_point() + xlim(0, plot_limits_d()$xlim_max) + ylim(0, plot_limits_d()$ylim_max)
  })

}

shinyApp(ui, server)