2015-03-23 16 views
10

Używam aplikacji Shiny, w której ustawienie suwaka na odpowiednią wartość może trochę potrwać.Shiny slider ogranicza reakcję na zwolnienie lewego przycisku myszy

Podczas próby ustawienia suwaka we właściwej wartości (i nie zwalniając lewego przycisku myszy!) Serwer (na przykład mój lokalny) zaobserwował kilka nowych wartości i odpowiednio zareagował.

jako odpowiedź mojego serwera na każdej nowej wartości może potrwać kilka sekund, byłbym zadowolony, gdybym mógł albo:

  • opóźnić sygnalizację serwer aż do uwolnienia lewym przyciskiem myszy lub
  • po stronie serwera, przerwij wszelkie wcześniejsze odpowiedzi, jeśli otrzymają nową wartość

Odpowiedz

4

Dobra, po pewnym kopaniu, myślę, że znalazłem rozwiązanie. Wydaje się, że najczystszym sposobem na zrobienie tego, bez konieczności bałaganowania ze skryptem Java, byłoby użycie pakietu shinyCustom, który ma funkcję useShinyCustom i customSliderInput. Dzięki nim możesz ustawić reaktywność na "odbijanie", a także bałagan z czasem opóźnienia. Jeśli używałbyś tych opcji razem, powinieneś być w stanie znaleźć słodki punkt, by tylko aktualizować wyjście, gdy suwak przestanie się poruszać. To nie będzie idealne "po zwolnieniu przycisku myszy;" ale powinno być całkiem blisko!

Na przykład, można spróbować coś takiego:

# Slider delay type is actually "debounce" by default 
useShinyCustom(slider_delay = "500"), # Doubles the default delay time in ms 
customSliderInput("bins", #Use customSliderInput instead of sliderInput 
       "Number of bins:", 
       min = 1, 
       max = 50, 
       value = 30) 
+0

fajny pakiet. Rzeczywiście, jest to połowa drogi do rozwiązania pb ... – agenis

+0

tak, wyobrażam sobie, że jeśli użytkownik jest zainteresowany uzyskaniem dokładnie tego, o co prosił, prawdopodobnie mogliby zagłębić się w skrypt Java wygenerowany przez ten kod. Ale jest to trochę poza moim zasięgiem, jeśli chodzi o czas potrzebny na zbadanie sprawy. – creutzml

+2

Ten pakiet został napisany przed dodaniem ['debounce'] (https://shiny.rstudio.com/reference/shiny/1.0.4/debounce.html) i' przepustnicy'. Teraz łatwo jest wydłubać dowolne wejście - wystarczy owinąć wartość wejściową w reaktywny jak np. 'Debounce (reaktywny (input $ slider), 500)' –

2

Shiny na sliderInput wykorzystuje Ion.RangeSlider, która ma onFinish zwrotnego dla kiedy użytkownik zwolni ich myszy. To brzmi jak to, czego potrzebujemy.

Oto niestandardowe powiązanie wejścia dla "leniwego" wejścia suwaka, które sygnalizuje zmianę wartości tylko wtedy, gdy użytkownik zwolni swoją mysz (onFinish) lub gdy suwak zostanie zmieniony na siłę (onUpdate).

Dla przykładu, właśnie napisałem kod, który zmienia zachowanie ALL sliderInputs. Będziesz chciał przenieść to do zewnętrznego skryptu i dostosować dalej. Ponadto, onUpdate zostaje wywołany po zainicjowaniu suwaka, ale zanim Shiny zainicjuje wartości wejściowe. Musisz poczekać, aż Shiny zrobi to, aby wywołać wywołanie zmiany wartości w onUpdate. Rozwiązanie, w którym pracowałem, nie jest fantastyczne, ale byłem zbyt leniwy, aby znaleźć czystszy sposób.

library(shiny) 

ui <- fluidPage(
    tags$head(
    tags$script(HTML(" 
     (function() { 
     var sliderInputBinding = Shiny.inputBindings.bindingNames['shiny.sliderInput'].binding; 

     var lazySliderInputBinding = $.extend({}, sliderInputBinding, { 
      subscribe: function(el, callback) { 
      var $el = $(el); 
      var slider = $el.data('ionRangeSlider'); 

      var handleChange = function() { 
       if (!inputsInitialized) return; 
       callback(!$el.data('immediate') && !$el.data('animating')); 
      }; 

      slider.update({ 
       onUpdate: handleChange, 
       onFinish: handleChange 
      }); 
      }, 

      unsubscribe: function(el, callback) { 
      var slider = $(el).data('ionRangeSlider'); 
      slider.update({ 
       onUpdate: null, 
       onFinish: null 
      }); 
      } 
     }); 

     Shiny.inputBindings.register(lazySliderInputBinding, 'shiny.lazySliderInput'); 

     var inputsInitialized = false; 
     $(document).one('shiny:connected', function() { 
      inputsInitialized = true; 
     }); 
     })(); 
    ")) 
), 
    sliderInput("sliderA", "A", 0, 10, 5), 
    uiOutput("sliderB"), 
    verbatimTextOutput("sliderValues"), 
    actionButton("resetSliders", "Reset Sliders") 
) 

server <- function(input, output, session) { 
    observeEvent(input$resetSliders, { 
    updateSliderInput(session, "sliderA", value = 5) 
    updateSliderInput(session, "sliderB", value = c(4, 6)) 
    }) 

    output$sliderB <- renderUI({ 
    sliderInput("sliderB", "B", 0, 10, c(4, 6)) 
    }) 

    output$sliderValues <- renderPrint({ 
    cat(paste("Slider A =", input$sliderA), "\n") 
    cat(paste("Slider B =", paste(input$sliderB, collapse = " "))) 
    }) 
} 

shinyApp(ui, server) 
+0

dzięki, to jest to, czego potrzebuję, umieściłem go w 'lazy_slider. Plik js' jak zalecasz – agenis

Powiązane problemy