【问题标题】:Update Leaflet Marker based on timer in Shinydashboard基于 Shinydashboard 中的计时器更新传单标记
【发布时间】:2018-06-14 15:08:07
【问题描述】:

我有数据框df,它有两个变量latlon,现在我需要创建一个Shinydashboard,它通过在每个10 seconds 之后从数据框中获取下一行值来更新地图。

df

 df <- data.frame("Lat" = c(12.8882, 12.890, 12.891), "Lon" = c(77.58195,77.58190,77.581958))

Ui.R

library(shiny)
library(leaflet)
shinyUI( fluidPage(
                leafletOutput("map1")
                   )
        )

server.R

library(shiny)

 shinyServer(function(input, output, session) {

 output$mymap <- renderLeaflet({
                      leaflet() %>%
                        addTiles() %>%  # Add default OpenStreetMap map tiles
                        addMarkers(lng=df$lon, lat=df$lat)})
                               })

我只知道我可以使用invalidateLater() 来调用计时器,但我不知道如何实现它以增量读取数据框中的行。

Expected Result

我需要一张地图,其中marker 在每个10 Seconds 之后移动到下一个位置,移动标记的坐标通过数据框df 给出。

【问题讨论】:

    标签: r shiny leaflet


    【解决方案1】:

    您可以使用reactiveVal() 来跟踪当前显示的标记,并将observe()invalidateLater()leafletProxy() 结合使用来删除先前的标记并添加新的标记。为此,我们可以在每次添加标记时给图层一个layerId,然后我们可以在绘制下一个标记时使用它再次删除标记。

    下面给出了一个工作示例,我添加了一些 cmets 来说明正在发生的事情。希望这会有所帮助!



    library(shiny)
    library(leaflet)
    set.seed(1)
    
    df <- cbind(rnorm(40) * 2 + 13, rnorm(40) + 48)
    
    ui <- fluidPage(
      leafletOutput("mymap")
    )
    
    server <- function(input, output, session) {
    
      # Create the base map
      output$mymap <- renderLeaflet({
        leaflet() %>%
          addProviderTiles(providers$Stamen.TonerLite,
                           options = providerTileOptions(noWrap = TRUE)
          ) %>%
          setView(lng = mean(rnorm(1000) * 2 + 13), lat =  mean(rnorm(1000) + 48), zoom = 7)
      })
    
      # Initialize a reactiveVal to keep track of which point is currently selected
      point_to_plot <- reactiveVal(1)
    
      observe({
        # invalidate every 2 seconds
        invalidateLater(2000)
        isolate({
          # update point_to_plot() to next value. If next value is higher than the amount of rows
          # in df, set it to 1.
          point_to_plot(ifelse(point_to_plot()+1<=nrow(df),point_to_plot()+1,1))
          # Use leafletProxy to remove our previous marker, and add the new one.
          leafletProxy('mymap') %>%
            removeMarker('my_marker') %>%
            addMarkers(layerId = 'my_marker',data = df[point_to_plot(),,drop=F])
        })
      })
    
    }
    
    shinyApp(ui, server)
    

    编辑:使用您的数据的工作示例:

    library(shiny)
    library(leaflet)
    set.seed(1)
    
    df <- data.frame("Lat" = c(12.8882, 12.890, 12.891), "Lon" = c(77.58195,77.58190,77.581958))
    
    ui <- fluidPage(
      leafletOutput("mymap")
    )
    
    server <- function(input, output, session) {
    
      # Create the base map
      output$mymap <- renderLeaflet({
        leaflet() %>%
          addProviderTiles(providers$Stamen.TonerLite,
                           options = providerTileOptions(noWrap = TRUE)
          ) %>%
          setView(lat = 12.89, lng = 77.58195, zoom = 14)
      })
    
      # Initialize a reactieVal to keep trakc of which point is currently selected
      point_to_plot <- reactiveVal(1)
    
      observe({
        # invalidate every 2 seconds
        invalidateLater(2000)
        isolate({
          # update point_to_plot() to next value. If next value is higher than the amount of rows
          # in df, set it to 1.
          point_to_plot(ifelse(point_to_plot()+1<=nrow(df),point_to_plot()+1,1))
          # Use leafletProxy to remove our previous marker, and add the new one.
          leafletProxy('mymap') %>%
            removeMarker('my_marker') %>%
            addMarkers(layerId = 'my_marker',data = df[point_to_plot(),,drop=F])
        })
      })
    
    }
    
    shinyApp(ui, server)
    

    【讨论】:

    • @ANmike 请查看我的编辑,我使用您提供的数据添加了一个工作示例。
    • 太好了,很高兴我能帮上忙! :)
    • 这很有帮助,谢谢@Florian!我试图修改它以使用多个点。作为一个快速修改,如果不是 df[point_to_plot(),,drop=F] 我有 df[point_to_plot() + 0:1,,drop=F],它仍然只绘制一个点。 (它最终也会使 b/c 的下标崩溃超出范围,但我可以解决这个问题)。你知道还有什么需要修改的吗?
    • 嗨@bmac,这对于cmets 中的讨论来说非常广泛,也不清楚您对我的预期结果是什么。请考虑在 SO 上提出一个新问题,我会看看是否可以帮助您:)
    • 好的,谢谢@Florian!我将在第二天左右写一个问题,并在写完后在此处发布一个链接。基本上,我有兴趣显示沿不同直线路径移动的多个点/标记。这可以通过调整上面的代码来实现,使其在每帧中显示多个点,并将 invalidLater 减少到一个更小的数字。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 2017-02-16
    相关资源
    最近更新 更多