Search code examples
rshinyr-leaflet

display map just once (leaflet and shiny)


I have gps data and would like to display it nicely on a map. I need to do an animation that depends on time - basically, track an individual over time on a map. The problem that I am facing here is that when I click on the time slider to run (animation) the map reloads every time there is a new point in time. I would like the map to be loaded only once when I open the app and the points appear as time goes by for a selected userid.

library(shiny)
library(leaflet)
library(lubridate)
library(shinydashboard)
library(tidyverse)

latitude=c(37.4218, 37.4063)
longitude=c(-124.0831, -124.1190)
userid=c(1704, 1704)
time=c("2017-09-15 14:40:58", "2017-09-15 14:53:35")

## reproducible data 
geo<- as.data.frame(cbind(latitude,
        longitude, 
        userid, 
        time))

## data manipulation
geo<- geo %>% 
mutate(time = ymd_hms(time))%>% 
mutate(longitude=as.numeric(longitude), 
     latitude=as.numeric(latitude), 
     userid=as.numeric(userid))


region<- "US" ##"US" / "Boston" select region of initial view

if (region=="US") {
  lngset = -93.85
  latset = 37.45
  zoomset = 4
}
if (region=="Boston") {
  lngset = ## update
  latset = ## update
  zoomset = ## update
}

mindate<-min(geo$time)
maxdate<-max(geo$time)

IDS<-unique(geo$userid)

ui=fluidPage(
   titlePanel("title"),
   leafletOutput("mymap",height = 500),
   selectInput(inputId = "userid", 
          label="user id", 
          choices = IDS),
    sliderInput("date_range", 
          "Choose Date:", 
          min = mindate, 
          max = maxdate, 
          step = 1, ## by minute 
          value = mindate,
          animate = animationOptions(loop = TRUE, interval = 1000))
)




server <- function(input,output){

 display only location for an hour for a chosen used
 data <- reactive({
   x <- geo %>% ## 
     filter(time<=input$date_range & time>=input$date_range-hours(1), 
userid==input$userid)
 })


  output$mymap <- renderLeaflet({
   df <- data()

    m <- leaflet(data = df) %>%
     setView(lng = lngset, lat = latset, zoom = zoomset) %>% ## center 
     addTiles() %>%
     addCircles(lng = ~longitude,
                lat = ~latitude,
                 popup = paste("User", df$userid, "<br>",
                              "Year:", df$time))
    m


  })



}

## deploy the app
shinyApp(ui=ui, server=server)

Solution

  • I will try this:

    library(shiny)
    library(leaflet)
    library(lubridate)
    library(shinydashboard)
    library(tidyverse)
    
    latitude=c(37.4218, 37.4063)
    longitude=c(-124.0831, -124.1190)
    userid=c(1704, 1704)
    time=c("2017-09-15 14:40:58", "2017-09-15 14:41:03")
    
    ## reproducible data 
    geo<- as.data.frame(cbind(latitude,
                              longitude, 
                              userid, 
                              time),stringsAsFactors = F)
    
    ## data manipulation
    geo<- geo %>% 
       mutate(time = ymd_hms(time)) %>%
       mutate(longitude=as.numeric(longitude), 
              latitude=as.numeric(latitude), 
           userid=as.numeric(userid))
    
    
    region<- "US" ##"US" / "Boston" select region of initial view
    
    if (region=="US") {
      lngset = -93.85
      latset = 37.45
      zoomset = 4
    }
    olddf <- data.frame()
    
    mindate<-min(geo$time)
    maxdate<-max(geo$time)+hours(1)
    
    IDS<-unique(geo$userid)
    
    ui=fluidPage(
      titlePanel("title"),
      leafletOutput("mymap",height = 500),
      selectInput(inputId = "userid", 
                  label="user id", 
                  choices = IDS),
      sliderInput("date_range", 
                  "Choose Date:", 
                  min = mindate, 
                  max = maxdate, 
                  step = 1, ## by minute 
                  value = mindate,
                  animate = animationOptions(loop = TRUE, interval = 1000))
    )
    
    
    
    
    server <- function(input,output){
    
      #display only location for an hour for a chosen used
      data <- reactive({
        x <- geo %>% ## 
          filter(time<=input$date_range & time>=input$date_range-hours(1), 
                 userid==input$userid)
      })
    
     observe({
        df <- data()
        print(df)
        leafletProxy("mymap",data = df) %>%
        #  setView(lng = lngset, lat = latset) %>% ## center 
          addTiles() %>%
          addCircles(lng = ~longitude,
                     lat = ~latitude,
                     popup = paste("User", df$userid, "<br>",
                                   "Year:", df$time))
      })
      output$mymap <- renderLeaflet({
        m <- leaflet() %>%
          setView(lng = lngset, lat = latset, zoom = zoomset) %>% ## center 
          addTiles() 
        m
    
    
       # m <- leaflet() %>%
        # #  setView(lng = lngset, lat = latset, zoom = zoomset) %>% ## center 
        #  addTiles() %>%
        #    addCircles(lng = ~longitude,
        #            lat = ~latitude,
                     #               #              popup = paste("User", df$userid, "<br>",
        #                     "Year:", df$time))
    # 
    #  m
    
      })
    
    
    
    }
    
    ## deploy the app
    shinyApp(ui=ui, server=server)
    
    1. Be carefull when you convert from factor to numeric. Observe differences between

    geo<- as.data.frame(cbind(latitude, longitude, userid, time))

    ## data manipulation
    geo<- geo %>% 
    mutate(time = ymd_hms(time))%>% 
    mutate(longitude=as.numeric(longitude), 
         latitude=as.numeric(latitude), 
         userid=as.numeric(userid))
    

    and

    ## reproducible data 
    geo<- as.data.frame(cbind(latitude,
                              longitude, 
                              userid, 
                              time),stringsAsFactors = F)
    
    ## data manipulation
    geo<- geo %>% 
       mutate(time = ymd_hms(time)) %>%
       mutate(longitude=as.numeric(longitude), 
              latitude=as.numeric(latitude), 
           userid=as.numeric(userid))
    
    1. To modify real time a leaflet use leafletProxy (https://rstudio.github.io/leaflet/shiny.html). I set setView(lng = lngset, lat = latset) %>% ## center as commented code because we do not want to redraw the map every time the user zoom or move around.

    Best!