仅当缩放级别>时,才在Shiny中显示传单地图中的图层. 8使用LayersControl? [英] Show layer in leaflet map in Shiny only when zoom level > 8 with LayersControl?

查看:109
本文介绍了仅当缩放级别>时,才在Shiny中显示传单地图中的图层. 8使用LayersControl?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只想在LayersControl中单击该图层并且缩放级别大于某个特定数字(例如)时显示该图层. 8.原因之一是,必须执行一些昂贵的计算才能获取层坐标.我想使用layerscontrol而不是一个额外的输入按钮(出于光学原因).

I want to show a layer only when its clicked in the LayersControl and the zoom level is greater than a certain number, e.g. 8. One of the reasons is, that some expensive computations must be performed to get the layer coordinates. I want to use the layerscontrol and not an extra input button (for optical reasons).

如果在layerscontrol中单击了layer按钮,是否可以检索该值?

Is there a way to retrieve the value, if the layer button is clicked in the layerscontrol?

这是一个简单的示例(不起作用):

Here is a simple example (not working):

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)

推荐答案

这是第一个正在运行的版本.也许smdy想出了更清洁"的方法:).

Here is a first running version. Maybe smdy comes up with sthg "cleaner" :).

这里有一个简短的解释:

Here a small explanation:

挑战1:input $ marker作为闪亮的输入不存在. 打开您的应用程序(在浏览器中),右键单击您感兴趣的标记输入,然后在浏览器中选择检查元素"或等效标签.您将看到该输入的代码. 那么,为什么您不能访问它呢?要查看您从发亮知道的输入类型的区别,请创建一个textinput或sthg并创建检查元素".您会看到闪亮的输入有一个ID,...标记输入没有

Challenge 1: input$marker does not exist as shiny input. Open your app (in a browser), make a right click on the marker input you are interested in and select "Inspect Element" or the equivilant label in your browser. You will see the code of that input. So why cant you access it. To see the difference to the kind of input you know from shiny, create a textinput or sthg and make "inspect element" as well. You see that the shiny-inputs have an id,....the marker input does not

挑战2:访问没有ID的输入 (从这里开始,您应该知道如何将消息从JS发送到R并返回:在这里,您会找到一篇很好的文章:. (注意:从现在开始,我假设您只有一个输入) 并且知道它有点棘手.尝试访问 此输入.通过console.log(),您可以打印到javascript控制台(并通过"F12"->控制台(JS)在运行的应用程序中将其打开.) 您可以将此输入打印为HtMLCollection,但不能访问它,这可能会非常混乱.

Challenge 2: Access input that does not have an id: (From here on you should know how to send messages from JS to R and back: A very good article you will find here: https://ryouready.wordpress.com/2013/11/20/sending-data-from-client-to-server-and-back-using-shiny/) How to access the input: Well, thats basically just finding the right snippet via google. In the end this: document.getElementsByTagName("input"). (Attention: From here on I assume you only have one input) And know it gets a bit tricky. Try to access this input. Via console.log() you can print to javascript console (and open it in the running app via "F12" --> Console (JS).) You can print this input as HtMLCollection but can not access it, which can be very confusing.

挑战3:访问HTMLCollection

(简而言之)您无法访问它的原因是在构建"DOM"之前调用了JS代码.如果在"<body></body>"之后调用脚本,那将完全正常.但是,用普通的香草光泽就不那么容易了.您可以尝试window.onload()document.ready(). 到目前为止,对我来说最可靠的方法是使用: session $ onFlushed()并触发该函数中的JSCode从R发送到"JS". (然后通过Shiny.onInputChange("marker", inputs[0].checked);将值作为输入发送回R)->这将产生所需的"input $ marker". 但是,此功能仅触发一次,这完全是正确的行为.但是,当您单击按钮时,您将没有更新.

The reason (in short) why you can not access it is that the JS code is called before the "DOM" is build. It would work totally fine if the script is called after "<body></body>". But thats not that easy with plain vanilla shiny. You can try window.onload() or document.ready(). What is the most reliable for me so far is to use: session$onFlushed() and trigger to send the JSCode within that function from R to "JS". (And then send the value as an input back to R via Shiny.onInputChange("marker", inputs[0].checked); ) --> This will produce the desired "input$marker". However, this function only fires once, which is totally right behaviour. But you wont have updates when you click the button.

挑战4:更新输入的$ marker 好吧,漂亮的版本将是具有功能.onclicked()/用于输入的侦听器.也许有人可以找到解决方案.我尝试了Shiny的变通办法,即告诉Shiny通过autoInvalidate()不断获取输入值.

Challenge 4: Update input$marker Well the pretty version would be to have a function .onclicked()/ a listener for the input. Maybe somebody could find a solution. I tried a workaround in shiny, that i tell shiny to constantly get value of the input via autoInvalidate().

挑战5: 好吧,这并不困难,因为它只是有光泽的,而是为了完整性.给定问题中提供的代码,标记将在加载一次后停留.如果不满足缩放条件,则不确定是否要保留它或将其删除. 无论如何,如果您希望它消失,%>% clearMarkers()是您的朋友.

Challenge 5: Well, not that difficult, because it is shiny only, but for sake of completeness. Given the provided code in the question, the marker will stay when loaded once. Not sure if you want it to stay or to be removed once your zooming criteria is not met. Anyway, if you want it to disappear, %>% clearMarkers() is your friend.

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)

这篇关于仅当缩放级别>时,才在Shiny中显示传单地图中的图层. 8使用LayersControl?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆