2015-03-23 9 views
10

Sto utilizzando un'applicazione lucida in cui potrebbe essere necessario del tempo per impostare un cursore sul valore corretto.Il cursore lucido limita la reazione al rilascio del pulsante sinistro del mouse

Quindi, mentre provavo a impostare il cursore sul valore corretto (e non rilasciare il tasto sinistro del mouse!) Il server (cioè il mio locale) ha osservato diversi nuovi valori e reagisce di conseguenza.

Poiché la risposta del mio server su qualsiasi nuovo valore può richiedere alcuni secondi Sarei lieto se potessi uno:

  • rinviare la segnalazione al server fino al rilascio del pulsante sinistro del mouse, o
  • sul lato server, interrompe eventuali risposte precedenti se riceve un nuovo valore

risposta

4

OK, dopo alcuni scavi, penso di aver trovato la soluzione. Sembra che il modo più pulito per farlo, senza la necessità di utilizzare lo script Java, sia utilizzare il pacchetto shinyCustom, che ha una funzione useShinyCustom e customSliderInput. Con questi, è possibile impostare la reattività su "rimbalzo" e anche con il tempo di ritardo. Se dovessi utilizzare queste opzioni insieme, dovresti essere in grado di trovare il punto debole solo per aggiornare l'output una volta che il cursore si ferma. Non sarà perfetto "al rilascio del pulsante del mouse;" ma dovrebbe essere dannatamente vicino!

Ad esempio, si può provare qualcosa di simile:

# 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

bel pacchetto. In effetti, è la metà strada da percorrere per risolvere il pb ... – agenis

+0

sì, sto immaginando se l'utente è interessato a ottenere esattamente quello che hanno richiesto, potrebbero probabilmente scavare nello script Java generato da questo codice. Ma è un po 'fuori dalla mia portata, per quanto riguarda il tempo di investigare. – creutzml

+2

Questo pacchetto è stato scritto prima di ['debounce'] (https://shiny.rstudio.com/reference/shiny/1.0.4/debounce.html) e' throttle' sono stati aggiunti. Ora è facile debounce/throttle qualsiasi input - solo avvolgere il valore di input in un reattivo come 'debounce (reactive (input $ slider), 500)' –

2

lucido di sliderInput utilizza Ion.RangeSlider, che ha un onFinish di callback per quando un utente rilascia il mouse. Sembra proprio quello di cui abbiamo bisogno.

Ecco un binding di input personalizzato per un input di scorrimento "pigro" che segnala solo un cambiamento di valore quando un utente rilascia il proprio mouse (onFinish) o quando il cursore viene aggiornato forzatamente (onUpdate).

Per l'esempio, ho appena inserito il codice che cambia il comportamento di ALL sliderInputs. Dovrai spostarlo su uno script esterno e personalizzare ulteriormente. Inoltre, onUpdate viene chiamato quando lo slider viene inizializzato, ma prima che Shiny inizializzi i valori di input. Devi aspettare fino a quando Shiny lo fa per chiamare la callback della modifica del valore in onUpdate. La soluzione in cui ho lavorato non è fantastica, ma ero troppo pigro per trovare un modo più pulito.

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

grazie, questo è davvero quello che mi serve, l'ho messo in un 'lazy_slider. js' file come si consiglia – agenis

Problemi correlati