【问题标题】:RShiny Leaflet- Getting data from measure toolR Shiny Leaflet- 从测量工具获取数据
【发布时间】:2019-06-12 19:54:53
【问题描述】:

我正在尝试获取用户在 RShiny Leaflet 地图上使用测量工具时的结果(具体区域)。根据leaflet-measure documentation,您可以在名为 measurestartmeasurefinish 的传单地图上订阅 2 个事件。我需要订阅这些事件并获取事件提供的结果数据,但我不知道如何。

我尝试了许多不同的方式来订阅该事件,但都没有被地图触发。

这是一些感觉最接近工作的代码:

observeEvent(input$map1_measurefinish, {
    print("user finished measurement")
})

observeEvent(input$measurefinish, {
    print("user finished measurement")
})

我的服务器部分的传单代码如下所示:

output$map1 <-renderLeaflet({
      m<-leaflet() %>%
      addProviderTiles('Esri.WorldImagery') %>%...
# there's more code here but I don't think its relevant for the issue

我需要做什么来 1. 正确订阅事件以检测测量何时完成 2. 接收输出数据以在观察者方法中执行操作?

编辑:解决方案(由@NicE 给出)

我对代码所做的更改以使其正常工作:

在传单里面添加了标记代码:

output$map1 <-renderLeaflet({
     m<-leaflet() %>%
     addMeasure() %>%
     # Start
     htmlwidgets::onRender("
        function(el, x) {
          var myMap = this;
          myMap.on('measurefinish',
          function (e) {
            Shiny.onInputChange('selectedArea', e.area);
            Shiny.onInputChange('inputtedCoordinates', e.lastCoord);
          })
        }")
     # End

另外添加了一个观察者(会做比打印更激动人心的事情):

observeEvent(input$selectedArea, {
    print(paste0("area received:", input$selectedArea))
})

【问题讨论】:

  • 我无法让它工作。我使用 tags$script(HTML()) R 函数将代码放入,但仍然无法获得接收处理程序的方法。也许我没有写接收器对吗?我假设函数名称“完成”或“点击”将是发送它的方法的名称,还是其他?
  • 如果您可以包含一个完全可重现的示例(在这种情况下是一个工作闪亮的应用程序),那就太好了。不仅仅是一些sn-ps。 ;)
  • @SeGa 很高兴知道,你所做的例子几乎就是我所做的一切,但下次我一定会记住的:)

标签: r shiny leaflet


【解决方案1】:

您可以利用onRender 函数将侦听器添加到插件事件。例如,您可以尝试:

leaflet() %>% addTiles() %>%
      fitBounds(-73.9, 40.75, -73.95,40.8) %>%
      addMeasure() %>%
      htmlwidgets::onRender("
        function(el, x) {
          var myMap = this;
          myMap.on('measurefinish',
            function (e) {
              Shiny.onInputChange('selectedArea', e.area);
            })
        }")

这会在measurefinish 上添加一个侦听器,并将area 传递给selectedArea 闪亮输入。您可以将e.area 更改为提及here 的任何字段。

这是一个 MWE:

library(leaflet)
library(shiny)


ui <- fluidPage(
  leafletOutput("mymap"),
  br(),
  textOutput("areaText")
)

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

  output$mymap <- renderLeaflet({
    leaflet() %>% addTiles() %>%
      fitBounds(-73.9, 40.75, -73.95,40.8) %>%
      addMeasure() %>%
      htmlwidgets::onRender("
        function(el, x) {
          var myMap = this;
          myMap.on('measurefinish',
            function (e) {
              Shiny.onInputChange('selectedArea', e.area);
            })
        }")
    })

  output$areaText <- renderText({
    paste("Area",input$selectedArea)
  })
}

shinyApp(ui, server)

【讨论】:

  • 这确实更好更干净;) 你知道如何在没有onRender 函数的情况下收听measurefinish 事件吗?
  • @Sega,不知道如果没有onRender 函数我会怎么做,因为没有该函数很难处理map 对象
  • 好的,谢谢,我认为应该可以通过 Id 获取 map-div 并添加 EventListener 来工作,但无法让它像那样工作。
  • 这确实对我有用!我最终向 selectedArea 添加了一个简单的观察者,这样我就可以在输入数据后立即处理数据,否则这很好。 (stackoverflow 告诉我,我不能给你一个小时的赏金)
  • 虽然我这里有 R 专家,但(SeGa/NicE)如果你们两个知道我如何检测用户何时删除先前创建的区域块以及有多少区域,我'我很乐意为此奖励你一些赏金:)(我的最终目标是确定用户测量的总面积)
【解决方案2】:

这是使用来自leafletaddMeasure() 函数和一些JavaScript 的方法。

JavaScript 部分当然可以通过一些事件委托进行优化,因为按钮是动态呈现的。因此,我使用了一个 setTimeout 函数,它每秒重新评估一次。我确信这可以以更顺畅的方式完成,但我不是 JS 专家。 ;)

JavaScript 代码等待点击 完成测量 按钮并从此 HTML 部分 $('.js-results').children()[2].innerText 获取结果。 然后使用Shiny.onInputChange 将其传递给measurefinish,以便您可以使用input$measurefinish 在服务器代码中访问此值。

一种可能的解决方案:

library(shiny)

library(leaflet)

js <- HTML("
$(document).on('shiny:connected', function(event) {
   setTimeout(function(){
    var fin = document.getElementsByClassName('js-finish');
    fin[0].addEventListener('click', function eventHandler(event) {
      var area = $('.js-results').children()[2].innerText;
      Shiny.onInputChange('measurefinish', area);
    });
  }, 1000);
});
")

ui <- fluidPage(
  tags$head(tags$script(js)),
  leafletOutput("map1"),
  verbatimTextOutput("area")
)

server <- function(input, output, session) {
  output$map1 <-renderLeaflet({
    m<-leaflet() %>%
      addMeasure() %>%
      addProviderTiles('Esri.WorldImagery')
    m
  })


  output$area <- renderText({
    req(input$measurefinish)
    area <- input$measurefinish
    area <- gsub(pattern = "\n", "", x = area, fixed = T)
    ## Convert to numeric value 
    # area <- regmatches(area, regexpr("\\(?[0-9,.]+", area))
    # area <- as.numeric(gsub(pattern = ",", "", area, fixed=T))
    area
  })
}

shinyApp(ui, server)

根据您对@NicE 回答的评论,我编辑了他的代码以总结所有面积测量值。我正在使用一个 reactiveValues 对象来汇总该区域。要将总面积重置为 0,我使用 actionButtonobserveEvent 部分。

library(leaflet)
library(shiny)

ui <- fluidPage(
  leafletOutput("mymap"),
  br(),
  actionButton("resetArea", label = "Reset total area to 0"),
  textOutput("areaText"),
  textOutput("areaSumText")
)

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

  output$mymap <- renderLeaflet({
    leaflet() %>% addTiles() %>%
      fitBounds(-73.9, 40.75, -73.95,40.8) %>%
      addMeasure() %>%
      htmlwidgets::onRender("
        function(el, x) {
          var myMap = this;
          myMap.on('measurefinish',
            function (e) {
              Shiny.onInputChange('selectedArea', e.area);
            })
        }")
  })

  totalArea <- reactiveValues(sum = NULL)

  observe({
    req(input$selectedArea)
    isolate({
      if (is.null(totalArea$sum)) {
        totalArea$sum = input$selectedArea
      } else {
        totalArea$sum = totalArea$sum + input$selectedArea
      }
    })
  })
  observeEvent(input$resetArea, {
    totalArea$sum = NULL
  })

  output$areaText <- renderText({
    paste("Area",input$selectedArea)
  })
  output$areaSumText <- renderText({
    req(totalArea$sum)
    paste("Sum of Area",totalArea$sum)
  })

}

shinyApp(ui, server)

【讨论】:

  • 只是出于好奇,您是否仔细查看了measurefinish。我看到它在github.com/rstudio/leaflet/blob/… 中触发(以及在相应的(引用的)min.js 版本中),但是在开始闪亮时我看不到该事件(在控制台中使用getEventListeners(document.getElementById('MAPID'),...)。简化对 shinyjs::onevent("measurefinish", "MAPID", function(event){getdata...}) 的 JS 调用会很好。被困在那里,我很好奇:) - 无论如何都很好的答案(+1)!
  • 是的,我尝试使用measurefinish,但也无法使其与闪亮或控制台一起使用。但我不确定它是否足以在控制台中传递闪亮的 MAPID 而不是在 JS 中完全启动地图?
  • 我尝试仅在 JS 中启动地图,但我也无法触发该事件。显然这只适用于 Firefox,因为 leaflet-measure.min.js 无法在 Chrome / IE 或 Edge 中加载..
猜你喜欢
  • 2021-12-20
  • 2017-08-20
  • 2023-02-07
  • 2020-07-12
  • 1970-01-01
  • 1970-01-01
  • 2019-02-03
  • 2017-05-20
  • 1970-01-01
相关资源
最近更新 更多