Add different pictures to each Markers in the Leaflet Package (Map Application)

Hello everyone,

Hello to all of you,

I'm making an interactive R map with the Leaflet package, the application domain is related to zoology with the distribution of the Hedgehogs of the World.

Luckily I have already found some well done tutorials on the internet to train myself and produce the result.

Nevertheless, to make it perfect I still have a problem with one thing of great importance.

Here's my code

# - - -  Project Map Hedgehogs 


library(shiny)

library(shinythemes)

library(leaflet)

library(leaflet.providers)

library(dplyr)

library(maps)

library(RColorBrewer)

library(leaflet.extras)

library(rworldxtra)

library(raster)

library(sf)

library(tidyverse)


# 0] Load data


Data_Herisson <- read.csv("XXXXX/Documents/Question hérisson.csv")


# 1] Color from a factor which is " Genus Name "


Genus_names <- Data_Herisson$genus_name  %>% unique()


# Palette de couleurs


library(RColorBrewer)

brewer.pal(n = 3, name = "Paired")

Color <- c("blue","red","green")


pal <- colorFactor(Color,domain = Genus_names)


# [FINAL] Afficher la carte 

Map_Herisson<-leaflet() %>%
  addProviderTiles("Esri.WorldImagery") %>%                                        
  addCircleMarkers(data = Data_Herisson,                                          
                   lat = ~latitude,                           
                   lng = ~longitude,                          
                   color = ~pal(Data_Herisson$genus_name),                        
                   stroke = FALSE,                                                
                   popup = paste("Taxinomie : ", Data_Herisson$complete_name,
                                 "<br>",
                                 "N° échantillonnage : ", Data_Herisson$specimen_code,
                                 "<br>","<br>","<hr>",
                                 "Mode de conservation : ", Data_Herisson$preservation_method,
                                 "<br>",
                                 "Date prélèvement : ", Data_Herisson$date_collected,
                                 "<br>",
                                 "Statut étude phylogénétique : ", Data_Herisson$phylogeny_status),
                   label = ~as.character(name),                                    
                   clusterOptions = markerClusterOptions(),                        
                   fillOpacity = 0.5)                                           




# Ajout LĂ©gende des Genres Ă  la Carte 

Map_Herisson %>% addLegend(data = Data_Herisson, 
                              position = "topright", 
                              pal = pal,
                              values = Data_Herisson$genus_name,
                              title = "Genres de Brentidae", 
                              opacity = 1)

Voici ce que j'obtiens ce qui est déjà très satisfaisant :


My question is the following, how can I display in the popup a photo of each specimen?

It would be possible to use a link to a photo of the taxon, but that would break the aesthetic and interactive interest of the thing.

I have already seen and understood how to add a photo that is displayed for each marker (Source : Add a pop-up with an image to a leaflet map in R) but I can't figure out how to do it knowing that my real dataset is much larger .... :frowning:

If this works, the result would be truly wonderful ! :smiley:

Thak you in advance, wishing you a great day

Yes, you can display a photo of each specimen.

But you will need to find a way to host your photos somewhere on a web server (a static directory of photos).

You can then use the link to the photo on a web server to build the HTML in popup (like you already are doing with the Taxonomie, N° échantillonnage and other fields. Displaying an image is in principle not that much different from displaying a horizontal ruler. Both are HTML tags, with only a slightly different syntax.

1 Like

Hello again,

First of all I thank you for your answer which was very useful, nevertheless some problems persist.

It does work from an internet picture link however ...I'm not sure how to resize my image, but I'd like to know how to do it, because it's huge and it's too big to fit in the frame.

Also, could you please give me an example of a web server? I have already tried Dropbox or ImgBB which store pictures and provide me an acess link but unfortunately it doesn't work, the link is probably not included -> An example is provided in the code.

Here is my code:



# [FINAL] Show the map 

Map_Herisson<-leaflet() %>%
  addProviderTiles("Esri.WorldImagery") %>%                                        
  addCircleMarkers(data = Data_Herisson,                                          
                   lat = ~latitude,                           
                   lng = ~longitude,                          
                   color = ~pal(Data_Herisson$genus_name),                        
                   stroke = FALSE,                                                
                   popup = paste(paste0("<img src='https://www.r-project.org/logo/Rlogo.png", "' />"),
                                 "<br>","<br>",
                                 "Taxinomie : ", Data_Herisson$complete_name,
                                 "<br>",
                                 "N° échantillonnage : ", Data_Herisson$specimen_code,
                                 "<br>","<br>","<hr>",
                                 "Mode de conservation : ", Data_Herisson$preservation_method,
                                 "<br>",
                                 "Date prélèvement : ", Data_Herisson$date_collected,
                                 "<br>",
                                 "Statut étude phylogénétique : ", Data_Herisson$phylogeny_status),
                   label = ~as.character(name),                                    
                   clusterOptions = markerClusterOptions(),                        
                   fillOpacity = 0.5)                                           


# Legend 

Map_Herisson %>% addLegend(data = Data_Herisson, 
                              position = "topright", 
                              pal = pal,
                              values = Data_Herisson$genus_name,
                              title = "Genres de Hedgehogs", 
                              opacity = 1)


# - - - - - - - - - 


# [FINAL] Map with picture from a dropbox link

Map_Herisson<-leaflet() %>%
  addProviderTiles("Esri.WorldImagery") %>%                                        
  addCircleMarkers(data = Data_Herisson,                                          
                   lat = ~latitude,                           
                   lng = ~longitude,                          
                   color = ~pal(Data_Herisson$genus_name),                        
                   stroke = FALSE,                                                
                   popup = paste(paste0("<img src='https://www.dropbox.com/s/9njtb9o9lql25o0/atelerix_algirus.jpg?dl=0", "' />"),
                                 "<br>","<br>",
                                 "Taxinomie : ", Data_Herisson$complete_name,
                                 "<br>",
                                 "N° échantillonnage : ", Data_Herisson$specimen_code,
                                 "<br>","<br>","<hr>",
                                 "Mode de conservation : ", Data_Herisson$preservation_method,
                                 "<br>",
                                 "Date prélèvement : ", Data_Herisson$date_collected,
                                 "<br>",
                                 "Statut étude phylogénétique : ", Data_Herisson$phylogeny_status),
                   label = ~as.character(name),                                    
                   clusterOptions = markerClusterOptions(),                        
                   fillOpacity = 0.5)                                           


# Legend 

Map_Herisson %>% addLegend(data = Data_Herisson, 
                           position = "topright", 
                           pal = pal,
                           values = Data_Herisson$genus_name,
                           title = "Genres de Hedgehogs", 
                           opacity = 1)

Thanks again for your help

You may want to tune your images, or perhaps use the width and height arguments of IMG tag more actively.

Consider this piece of code; note the use of single quotes to delimit strings, so that double quotes will remain safely inside (and utilized by the HTML call). Also note how I replaced the zero at the end of your link with a 1; a neat trick I found at https://support.exclaimer.com/hc/en-gb/articles/360018586691-How-to-host-an-image-using-Dropbox

library(sf)
library(dplyr)
library(leaflet)


a_point <- nominatimlite::geo_lite_sf("Clermont-Ferrand") %>% # looks about right
  mutate(label = paste0("lo & behold: a hedgehog",
                        '<img src=',
                        '"https://www.dropbox.com/s/9njtb9o9lql25o0/atelerix_algirus.jpg?dl=1"',
                        'alt="no longer stolen from wikipedia"',
                        'width="300"',
             #           'height="250"',
                        '>'))

leaflet(data = a_point) %>% 
  addProviderTiles("Esri.WorldImagery") %>% 
  addMarkers(popup = ~label) %>% 
  setView(lat = 50.073658, 14.418540, zoom = 4) # view centered on Prague (just because...)

2 Likes

Wow wonderful, it works, thank you very much for your help

Actually I have one last question before I can shout hurrah: How can I add to each point its corresponding taxon image like on the image below?

Should I insert the dropbox link directly into the dataframe and then call it in the html link to display it? Is this possible?

Or

Should I list the dropbox image link in the tag in the same order as the species listed in the data frame? I don't know...

Especially since my actual sample covers about 50 individuals, so an economical and practical solution would of course be preferable if possible... Otherwise it doesn't matter

Opravdu mi hodně pomáháte a to je cenné, takže děkuji :clap:

Glad to be of service!

I don't know enough about your use case to give a definite answer, but the way I would approach the problem in your shoes would be somehow along these lines:

  • upload all images to your preferred hosting provider (Dropbox or what not; the principle remains)
  • in the data frame that forms the "data" argument of your leaflet call (it seems to be named Data_Herisson) I would add a column with the link to the image - this could have one to one relationship to your observation (each row / observation having a unique link to an unique image) or one to many (several rows having the same link to the same image / repeated observations of the same taxon)
  • when constructing the HTML of the popup I would wrap this column with link inside the <IMG src = blah blah blah> call

And since you made me curious about your work - if your final result get posted somewhere on the internet, do me a favor and drop me a link! Hedgehogs are cute, I would love to have a look :slight_smile:

I would go this way. Add links to dataframe, make sure the coordinates are there as well and voila.

You can have two different dataframes as well: one with observations, second with geocoded photos. Assuming location, description is written in EXIF, you can use exiftoolr to get the dataframe build. That was my last attempt:



library(exiftoolr)
photos <- exif_read(path = "photos", recursive = TRUE)

map <- leaflet(my_data$geometry)
map <- addTiles(map)
map <-   addPolylines(map, color = "#0000FF")
for (i in 1:nrow(photos)) {
  map <- addMarkers(map, 
                    lng = photos[i,"GPSLongitude"], 
                    lat = photos[i,"GPSLatitude"], 
                    popup = paste0("<a href = photos/", photos[i, "FileName"], 
                            " target = \"_blank\">", "<img src = photos/", 
                            photos[i, "FileName"], " width = \"300\">", "</a>"))
}
map

however photos are hosted locally.

Mmmmmmm

Thank you for your two answer ! I will see this even if I think it will be a little too hard at my level for now ...

I will come back soon, if it does function you will be thanked by all the zoologist in the world ahahaha

A stupid solution would be to do as many dataframe as species and call for the picture i Guess in the link wich is very bad ahahaha

No, it not will be stupid. Neither silly. Every solution which brings you to expected result is good.

Our knowledge evolve with time. Not only about R and coding, but everything. When we learn new things, we can look back and -- in case of coding -- improve our code. Implement an existing or new functions, expand it, or minimize it. But as long as it works (regardless of implementation, number of lines of code, whatever) -- is the best one.

Regards,
Grzegorz