简体   繁体   English

在 Shiny 中同步 Dygraph 和 DateRangeInput

[英]Synchronise Dygraph and DateRangeInput in Shiny

I would like to synchronise a dygraph and a DateRangeInput inside a Shiny App.我想在 Shiny App 中同步一个 dygraph 和一个 DateRangeInput。 The code bellow works fine: I can simultaneously use the zoom option And the daterange but I can't use the dyRangeSelector because of a "ping pong" Effect:下面的代码工作正常:我可以同时使用缩放选项和日期范围但由于“乒乓”效果我不能使用dyRangeSelector:

library(xts)
library(shiny)
library(dygraphs)
library(lubridate)


data("co2")
data <- as.vector(coredata(as.xts(co2)))
serie <-  xts(x = data,order.by = seq(from=today(),by=1,length.out = length(data)))
ui <- fluidPage(
   titlePanel("Dygraph & date range input"),
   sidebarLayout(
      sidebarPanel(
        dateRangeInput('plage', label = "Selectionnez la période :",
                        start = start(serie), end = end(serie),
                         # min = start(serie), max = end(serie),
                       separator = " - ", 
                       format = "dd mm yyyy", #"yyyy-mm-dd",
                       language = 'fr', weekstart = 1
        )
      ),
      mainPanel(
         dygraphOutput("dessin")
      )
   )
)

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

observeEvent(input$dessin_date_window,{
  start <- as.Date(ymd_hms(input$dessin_date_window[[1]]))
  stop  <- as.Date(ymd_hms(input$dessin_date_window[[2]]))
  updateDateRangeInput(session = session,
                       inputId = "plage",
                       start = start,end = stop
                       )
})

  output$dessin <- renderDygraph({
      dygraph(serie) %>%
    dyRangeSelector(
      dateWindow = input$plage+1) # +1 parce que voila...
  })
}

# Run the application 
shinyApp(ui = ui, server = server)

Any idea how to control that?知道如何控制吗? (there is no update function for dygraph... :( ) (dygraph 没有更新功能...:( )

Just add a reactive for the current series and you should be good只需为当前系列添加一个反应,你应该很好

  current_series <- reactive({
    range <- paste(input$plage[1], input$plage[2], sep = "/")
    serie[range]
  })

  output$dessin <- renderDygraph({
    dygraph(current_series()) %>%
      dyRangeSelector(
        dateWindow = input$plage+1) # +1 parce que voila...
  })

You can define values that will check if the change is triggered by the user or by the reactivity.您可以定义将检查更改是由用户触发还是由反应触发的值。 This allows you to control a chain reaction.这使您可以控制连锁反应。
Because the dygraph is an output, I need to add an intermediate value that will change only if not triggered by the automatic reaction.因为 dygraph 是一个输出,我需要添加一个中间值,只有在自动反应不触发时才会改变。 Thus, the dygraph updates if we interact with it, or if triggered by the date selector.因此,如果我们与之交互,或者如果由日期选择器触发,则 dygraph 会更新。 But not when the date selector is triggered by a change on the dygraph.但不是当日期选择器由 dygraph 上的更改触发时。

library(xts)
library(shiny)
library(dygraphs)
library(lubridate)


data("co2")
data <- as.vector(coredata(as.xts(co2)))
serie <-  xts(x = data,order.by = seq(from=today(),by=1,length.out = length(data)))

ui <- fluidPage(
  titlePanel("Dygraph & date range input"),
  sidebarLayout(
    sidebarPanel(
      dateRangeInput('plage', label = "Selectionnez la période :",
                     start = start(serie), end = end(serie),
                     separator = " - ", 
                     format = "dd mm yyyy", #"yyyy-mm-dd",
                     language = 'fr', weekstart = 1
      )
    ),
    mainPanel(
      dygraphOutput("dessin")
    )
  )
)

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

  r <- reactiveValues(
    change_datewindow = 0,
    change_plage = 0,
    change_datewindow_auto = 0,
    change_plage_auto = 0,
    plage = c( start(serie), end(serie))
  )


  observeEvent(input$dessin_date_window, {
    message(crayon::blue("observeEvent_input_dessin_date_window"))
    r$change_datewindow <- r$change_datewindow + 1
    if (r$change_datewindow > r$change_datewindow_auto) {

      r$change_plage_auto <- r$change_plage_auto + 1
      r$change_datewindow_auto <- r$change_datewindow

      start <- as.Date(ymd_hms(input$dessin_date_window[[1]]))
      stop  <- as.Date(ymd_hms(input$dessin_date_window[[2]]))
      updateDateRangeInput(session = session,
                           inputId = "plage",
                           start = start,end = stop
      )
    } else {
      if (r$change_datewindow >= 10) {
        r$change_datewindow_auto <- r$change_datewindow <- 0
      }
    }
  })

  observeEvent(input$plage, {
    message("observeEvent_input_plage")
    r$change_plage <- r$change_plage + 1
    if (r$change_plage > r$change_plage_auto) {
      message("event input_year update")

      r$change_datewindow_auto <- r$change_datewindow_auto + 1
      r$change_plage_auto <- r$change_plage

      r$plage <- input$plage

    } else {
      if (r$change_plage >= 10) {
        r$change_plage_auto <- r$change_plage <- 0
      }
    }
  })

  output$dessin <- renderDygraph({
    message("renderDygraph")
    dygraph(serie) %>%
      dyRangeSelector(
        dateWindow = r$plage + 1) # +1 parce que voila...
  })
}

# Run the application 
shinyApp(ui = ui, server = server)

Note that I added a reset of the counters when above 10. This is too avoid the trigger value to be to high for R. When the counter resets, you may notice a small outburst, depending on the speed your users change the slider.请注意,我在超过 10 时添加了计数器的重置。这也避免了 R 的触发值太高。当计数器重置时,您可能会注意到一个小的爆发,具体取决于用户更改滑块的速度。 You can increase this value to make it appear less often.您可以增加此值以减少它出现的频率。

I added some messages so that you can verify that there is not chain reaction.我添加了一些消息,以便您可以验证没有连锁反应。

You can use retainDateWindow = TRUE in dyRangeSelector() .您可以在dyRangeSelector()中使用retainDateWindow = TRUE

output$dessin <- renderDygraph({
  dygraph(serie) %>%
    dyRangeSelector(
      dateWindow = input$plage+1, retainDateWindow = TRUE)
})

I hope this helps you.我希望这可以帮助你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM