2017-01-15 24 views
2

我想僅在LayersControl中點擊並且縮放級別大於某個數字時才顯示圖層,例如, 8.其中一個原因是,必須執行一些昂貴的計算才能獲得圖層座標。我想使用圖層控件,而不是一個額外的輸入按鈕(出於光學原因)。只有在使用LayersControl縮放級別> 8時纔在Shiny中顯示傳單地圖中的圖層?

如果在layerscontrol中單擊圖層按鈕,是否有方法來檢索值?

下面是一個簡單的例子(不工作):

library(leaflet) 
library(shiny) 

ui <- fluidPage(
    leafletOutput("map", width = "100%", height = "700") 
) 

server <- function(input, output){ 
    output$map <- renderLeaflet({ 
    leaflet() %>% addTiles() %>% setView(10.4, 50.3, 7) %>% 
     addLayersControl(overlayGroups = c("marker"), 
         options = layersControlOptions(collapsed = FALSE)) 
    }) 

    observe({ 
    # if (input$marker == TRUE){ # how to get value if layercontrol is clicked? 
     if (input$map_zoom > 8) { 
     leafletProxy("map") %>% addMarkers(lng = 10.5, lat = 50, group = "marker") 
     } 
    # } 
    }) 
} 

shinyApp(ui = ui, server = server) 
+0

按[我對這個問題的評論](http://stackoverflow.com/q/41468538/5977215),我還沒有穿過的方法來進行反應,「layerControl」點擊。 – SymbolixAU

回答

3

這是第一個運行的版本。也許smdy想出了sthg「更清潔」:)。

這裏一個小的解釋:

挑戰1:輸入$標記不存在作爲閃亮的輸入。 打開您的應用程序(在瀏覽器中),右鍵點擊您感興趣的標記輸入,然後在瀏覽器中選擇「Inspect Element」或equivilant標籤。您將看到該輸入的代碼。 那你爲什麼不能訪問它。要查看與閃亮輸入類型的區別,請創建一個textinput或sthg並製作「檢查元素」。你看到發亮,輸入有一個id,......標記輸入不

挑戰2:訪問輸入不具有一個id: (從這裏開始,你應該知道如何發送郵件從JS到R和回來:一個非常好的文章,你會發現在這裏:https://ryouready.wordpress.com/2013/11/20/sending-data-from-client-to-server-and-back-using-shiny/) 如何訪問輸入:嗯,基本上只是通過谷歌找到正確的片段。最後這個:document.getElementsByTagName("input")。 (注意:從這裏開始,我假設你只有一個輸入) 並知道它有點棘手。嘗試訪問 這個輸入。通過console.log()您可以打印到JavaScript控制檯(並通過「F12」 - >控制檯(JS)打開它在運行的應用程序中。) 您可以將此輸入打印爲HtMLCollection,但無法訪問它,這可能非常令人困惑。

挑戰3:訪問的HTMLCollection

原因(簡稱),爲什麼你不能訪問它是JS代碼調用之前的「DOM」是構築。如果在「<body></body>」之後調用該腳本,它將完全正常工作。但用普通的香草光澤就不那麼容易了。您可以嘗試window.onload()document.ready()。 到目前爲止,我最可靠的是使用:session $ onFlushed()並觸發將該函數中的JS代碼從R發送到「JS」。 (然後通過Shiny.onInputChange("marker", inputs[0].checked)將值作爲輸入發送回R;) - >這將產生所需的「輸入$標記」。 但是,這個函數只會觸發一次,這是完全正確的行爲。但是當你點擊按鈕時你不會有更新。

挑戰4:更新輸入$標記 好漂亮的版本將有一個功能.onclicked() /對輸入的監聽器。也許有人可以找到解決方案。我嘗試了一種閃亮的解決方法,我告訴閃亮通過autoInvalidate()不斷獲得輸入值。

挑戰5: 好吧,沒那麼難,因爲它只有光澤,但爲了完整性。鑑於問題中提供的代碼,標記將在加載一次時保持不變。不確定是否希望在您的縮放條件未滿足時保留或刪除它。 無論如何,如果你想讓它消失,%>% clearMarkers()是你的朋友。

library(leaflet) 
library(shiny) 

getInputwithJS <- ' 
Shiny.addCustomMessageHandler("findInput", 
    function(message) { 
    var inputs = document.getElementsByTagName("input"); 
    Shiny.onInputChange("marker", inputs[0].checked); 
} 
); 
' 

ui <- fluidPage(

    leafletOutput("map", width = "100%", height = "700"), 
    tags$head(tags$script(HTML(getInputwithJS))) 
) 

server <- function(input, output, session){ 
    global <- reactiveValues(DOMRdy = FALSE) 
    output$map <- renderLeaflet({ 
    leaflet() %>% addTiles() %>% setView(10.4, 50.3, 7) %>% 
     addLayersControl(overlayGroups = c("marker"), 
         options = layersControlOptions(collapsed = FALSE)) 
    }) 

    autoInvalidate <- reactiveTimer(1) 

    observe({ 
    autoInvalidate() 
    if(global$DOMRdy){ 
     session$sendCustomMessage(type = "findInput", message = "")  
    } 
    }) 

    session$onFlushed(function() { 
    global$DOMRdy <- TRUE 
    }) 

    observe({ 
    if (!is.null(input$marker)){ 
     if (input$marker == TRUE){ # how to get value if layercontrol is clicked? 
     if (input$map_zoom > 8) { 
      leafletProxy("map") %>% addMarkers(lng = 10.5, lat = 50, group = "marker") 
     }else{ 
      leafletProxy("map") %>% clearMarkers() 
     } 
     } 
    } 
    }) 
} 

shinyApp(ui = ui, server = server) 
+0

非常好的答案。如果您添加了關於它正在執行的操作的解釋,將會有所幫助。 – SymbolixAU

+0

不錯的解決方案!它適用於最簡單的例子。但是我無法使用其他命名輸入(例如checkboxInputs等)更復雜的應用程序工作。那麼需要做哪些改變?這是否重要,我把標籤$ head部分放在UI中? – needRhelp

+0

Hi @needRhelp。在上面的代碼中添加:「var inputs = document.getElementsByTagName(」input「);」一行代碼「console.log(輸入)」。然後在瀏覽器中運行應用程序,並檢查日誌(F12 - 控制檯JS),並找到您的「標記輸入」具有哪個索引,並將該索引用於下一行代碼:「Shiny.onInputChange(」marker「,inputs [ 0] .checked);」你用nex索引代替0。希望有所幫助。 – BigDataScientist

相關問題