2

When making maps in R using Leaflet I often use images in the marker popups by putting an html line. I would like to make a leaflet map in Shiny that allows the user to select photos to go into the marker popups. When I do this from Shiny, the container shows up without an image, and it doesn't allow me to click the image to go to its location on my machine, like a standalone leaflet map would. When I hover over the container, it does display the file name with file:/// out in front of it, just like it does when I output a leaflet map with htmlwidgets.

Below is a simple working example of the problem. You will just need a .jpg, png, or svg to upload.

 ui<-bootstrapPage(div(class="outer",
              tags$style(type ="text/css", ".outer {position: fixed; top: 41px; left: 0; right: 0; bottom: 0; overflow: hidden; padding: 0} #table{white-space: nowrap;}"),

            leafletOutput("map", width = "100%", height="100%"),
              absolutePanel(top = 10, right = 10, width=300, draggable=TRUE,style="background-color: rgba(217, 240, 209, 0.85); border-radius: 10px; padding: 10px",

            fileInput(inputId = "photos", label = "Include photos", multiple = T, accept = c('image/png', 'image/jpeg', 'image/svg'))
                       )))



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

 photos<- reactive({

if (is.null(input$photos))
  return(NULL)

infilee<-input$photos
dirr<-dirname(infilee[1,4])

#reassign that directory to all of the filenames
for ( i in 1:nrow(infilee)) {
  file.rename(infilee[i,4], paste0(dirr,"/",infilee[i,1]))}

photo<-list.files(dirr, full.names=TRUE)


  })



output$map <- renderLeaflet({

leaflet() %>% addProviderTiles("Esri.WorldImagery") %>% 
  fitBounds(-81, 34, -77, 40) %>% 

  addMeasure(
    position = "topleft", primaryLengthUnit = "meters", primaryAreaUnit = "acres", secondaryAreaUnit = "sqmeters",
    activeColor = "#ff6f69", completedColor = "#00a9ff")   

  })


observe({

if (is.null(input$photos))
  return(NULL)

photos()->phdata

popup<-paste0("<div><a target='_blank' href='",phdata,"'><img width=100%, height=100% src='", phdata,"' ></a></div>")

leafletProxy("map") %>% 
 addMarkers( lng=-81, lat=37,popup=popup)

   })
  }

 shinyApp(ui = ui, server = server)
LAD
  • 141
  • 1
  • 7
  • [This](https://stackoverflow.com/a/36434237/5894457) should help! – SBista Dec 06 '17 at 13:43
  • @SBista Thank you for your comment. The `popupImage()` function from `mapview` and the other method of shifting folders works fine for using leaflet from R. However, I am attempting to do the same with Shiny, which would allow a user to have the same functionality from the app. I've tried incorporating those techniques in Shiny, but I have not had any success. – LAD Dec 06 '17 at 16:59
  • One thing you could try is that save the image the user upload on `www` folder and display that image in your popup. I have tested it and this works! – SBista Dec 07 '17 at 09:45
  • @SBista I have tried that too. It works if I have an image that I want to display, but for this app I want the user to be able to make maps using their own images. I have not found a way to let a user insert a file into the `www` folder from the app itself – LAD Dec 08 '17 at 13:59
  • You can copy the file that user uploads from temporary folder to `www`. and then use `popupImage`. I tried that earlier and it seemed to work. – SBista Dec 08 '17 at 14:02
  • @SBista Can you post an answer that shows how a user can use `fileInput` to upload an image that will be passed to the www folder? I don't want to manually move the image to the www folder, because if I were to do it manually, I would just make a normal `leaflet` map – LAD Dec 08 '17 at 21:53

1 Answers1

1

Here is the code where I have copied the image files from the temorary folder to the www folder.

library(shiny)
library(leaflet)
library(mapview)

ui<-bootstrapPage(div(class="outer",
                      tags$style(type ="text/css", ".outer {position: fixed; top: 41px; left: 0; right: 0; bottom: 0; overflow: hidden; padding: 0} #table{white-space: nowrap;}"),

                      leafletOutput("map", width = "100%", height="100%"),
                      absolutePanel(top = 10, right = 10, width=300, draggable=TRUE,style="background-color: rgba(217, 240, 209, 0.85); border-radius: 10px; padding: 10px",

                                    fileInput(inputId = "photos", label = "Include photos", multiple = T, accept = c('image/png', 'image/jpeg', 'image/svg'))
                      )))



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

  photos<- reactive({

    if (is.null(input$photos))
      return(NULL)

    infilee<-input$photos
    dirr<-dirname(infilee[1,4])
    www_dir <- file.path(getwd(), "www")

    #rename the files and copy all the files to www directory
    for ( i in 1:nrow(infilee)) {
       file.rename(infilee[i,4], paste0(dirr,"/",infilee[i,1]))
      file.copy( paste0(dirr,"/",infilee[i,1]), www_dir)
      }

    #Since the file is saved in www directory, you just have to pass the file name
    photo<-list.files(www_dir)


  })



  output$map <- renderLeaflet({
    # print(tempdir())
    # print(tempfile())

    leaflet() %>% addProviderTiles("Esri.WorldImagery") %>% 
      fitBounds(-81, 34, -77, 40) %>% 
      addMeasure(
        position = "topleft", primaryLengthUnit = "meters", primaryAreaUnit = "acres", secondaryAreaUnit = "sqmeters",
        activeColor = "#ff6f69", completedColor = "#00a9ff")#%>%saveas(tempdir())    
  })


  observe({

    if (is.null(input$photos))
      return(NULL)

    photos()->phdata
    popup <- popupImage(phdata)
    leafletProxy("map") %>% 
      addMarkers( lng=-81, lat=37,popup=popup)

  })
}

shinyApp(ui = ui, server = server)

The output you get using this code is:enter image description here

Hope it helps!

SBista
  • 7,479
  • 1
  • 27
  • 58