Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update Leaflet Marker based on timer in Shinydashboard

Tags:

r

leaflet

shiny

I have data frame df which has two variables lat and lon, Now I need to create a Shinydashboard which updates the map by taking next row value in from the data frame after every 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)})
                               })

Only thing I know is I can use invalidateLater() to call the timer but I do not know how to implement that for the incremental reading of the rows in the data frame.

Expected Result

I need a map where the marker moves to the next position after every 10 Seconds, The coordinates for moving the marker is given through the data frame df.

like image 465
ANmike Avatar asked Jun 14 '18 05:06

ANmike


1 Answers

You can use a reactiveVal() to keep track of the currently displayed marker, and use observe() in combination with invalidateLater() and leafletProxy() to remove the previous marker and add the new one. To do so we can give the layer a layerId everytime we add our marker, which we can then use to remove the marker again when plotting the next marker.

A working example is given below, I added some comments to illustrate what is happening. Hope this helps!


enter image description here


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)

EDIT: Working example with your data:

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)
like image 98
Florian Avatar answered Sep 27 '22 21:09

Florian