How can I add a local image on a map in leaflet? - r

I want to put a local image onto my leaflet map in R like this (I put the image manually in paint):
I tried this based on the example in ?mapview::addLogo:
library(mapview)
library(leaflet)
cities <- read.csv(textConnection("
City,Lat,Long,Pop
Boston,42.3601,-71.0589,645966
Hartford,41.7627,-72.6743,125017
New York City,40.7127,-74.0059,8406000
Philadelphia,39.9500,-75.1667,1553000
Pittsburgh,40.4397,-79.9764,305841
Providence,41.8236,-71.4222,177994
"))
img1 <- system.file("img1.png", package = "png")
leaflet(cities) %>%
addTiles() %>%
addCircles(lng = ~Long, lat = ~Lat, weight = 1,
radius = ~sqrt(Pop) * 30, popup = ~City)%>%
addLogo(img1, src = "local", position = "bottomright", alpha = 0.3)
but it didn't add the image to the map:

You're getting confused (and with good reason, it's a confusing help example) by the example in the help for ?addLogo. All addLogo needs is the path to the image. The call to system.file used in that help example just returns the path to a sample image included in the png package that was used for example purposes. If you already know the path to your image, you can just supply that.
Therefore, assuming that your image is named img1.png and is in the current working directory, you can just do this:
leaflet(cities) %>%
addTiles() %>%
addCircles(lng = ~Long, lat = ~Lat, weight = 1,
radius = ~sqrt(Pop) * 30, popup = ~City)%>%
addLogo("img1.png", src = "local",position = "bottomright", alpha = 0.3)

Related

How to resize large images in R Leaflet marker popups?

My code:
library(leaflet)
df <- as.data.frame(read.csv("arts.csv"))
file <- as.character(df$url)
leaflet() %>% addTiles()
%>% addMarkers(data = df, lng = ~lon, lat = ~lat,
popup = paste0("<img src = ", file, ">"))
%>% popupOptions(maxWidth = "auto")
I used some code snippet from here: Image in R Leaflet marker popups
My question is: how can I easily resize large images appearing in popups?
The illustartion of the problem:
For Example, I would like to make this photo of Cave Rapa Nui smaller to fit the pop-up.
Thank you in advance!
You can adjust the size by using the HTML width attribute.
Edit your code from above to e.g.
map <- leaflet() %>%
addTiles() %>%
addMarkers(data = df,
lng = ~lon,
lat = ~lat,
popup = paste0("<img src = ", file, " width = 300>"))
map # print the map

Link to image in popup (R leaflet)

I used the code mentioned in other topics here:
link <- c("https://lh4.googleusercontent.com/4okYLMcxk2ZjRqWwSwU8WkEcRQA4NRYxYrlZjieGCace9oNl2DYC78-ZsfIUxu2GKh2_SoPOWluXll2Sl5P0uJxCDPFW_uzQqsW_oHOQ9ept44Ex87I0yw_5EhD6nR1aIRiM")
addCircleMarkers(lng = ~ X, lat = ~ Y, radius = 3, fillColor = ~ species_5,
stroke = F, fillOpacity = 0.5,
popup = paste0("<img src='", link, "' />")
But image doesn't appear in the popup window. Since this image is uploaded from KML file, the link doesnt have ".jpg" part. You can check link. How to refer to that with aim to show image in the popup?
Thanks
Providing a reproducible example would make it easier to solve your issue. Here's one that works for me:
library(leaflet)
data(quakes)
link <- "https://lh4.googleusercontent.com/4okYLMcxk2ZjRqWwSwU8WkEcRQA4NRYxYrlZjieGCace9oNl2DYC78-ZsfIUxu2GKh2_SoPOWluXll2Sl5P0uJxCDPFW_uzQqsW_oHOQ9ept44Ex87I0yw_5EhD6nR1aIRiM"
leaflet(data = quakes[1:20,]) %>% addTiles() %>%
addMarkers(~long, ~lat, label = ~as.character(mag), popup = paste0("<img src = ", link, " />"))

R leaflet search marker NOT work

I was able to use these 2 packages to search the markers on the map. However, I just installed them on my new computer again, but the search button does not work now. How to search markers?
Thank you
# We need latest leaflet package from Github, as CRAN package is too old.
devtools::install_github('rstudio/leaflet')
devtools::install_github('bhaskarvk/leaflet.extras')
library("leaflet")
library("leaflet.extras")
cities <- read.csv(textConnection("
City,Lat,Long,Pop
Boston,42.3601,-71.0589,645966
Hartford,41.7627,-72.6743,125017
New York City,40.7127,-74.0059,8406000
Philadelphia,39.9500,-75.1667,1553000
Pittsburgh,40.4397,-79.9764,305841
Providence,41.8236,-71.4222,177994
"))
leaflet(cities) %>% addProviderTiles(providers$OpenStreetMap) %>%
addCircleMarkers(lng = ~Long, lat = ~Lat, weight = 1, fillOpacity=0.5,
radius = ~sqrt(Pop)/50 , popup = ~City, label=~City, group
='cities') %>%
addResetMapButton() %>%
addSearchFeatures(
targetGroups = 'cities',
options = searchFeaturesOptions(
zoom=12, openPopup = TRUE, firstTipSubmit = TRUE,
autoCollapse = TRUE, hideMarkerOnCollapse = TRUE )) %>%
addControl("<P><B>Hint!</B> Search for ...<br/><ul><li>New York</li>
<li>Boston</li><li>Hartford</li><li>Philadelphia</li><li>Pittsburgh</li>
<li>Providence</li></ul></P>",
position='bottomright')
I was having the same issue using the same example you provided. I was able to figure out that, for some reason, addSearchFeatures() will NOT work with addCircleMarkers(), but it does work with addMarkers(). So I used a workaround that essentially plots the same data twice: the first time using addCircleMarkers() with your desired formatting settings and the second time using addMarkers() with a custom icon that is so small you cannot see it on the map. The key is to assign each to the appropriate group. The search bar will search the "invisible" Markers layer but the "CircleMarkers" will be the ones that appear on your map.
# using the same reproducible data from the question/example
cities <- read.csv(
textConnection("City,Lat,Long,Pop
Boston,42.3601,-71.0589,645966
Hartford,41.7627,-72.6743,125017
New York City,40.7127,-74.0059,8406000
Philadelphia,39.9500,-75.1667,1553000
Pittsburgh,40.4397,-79.9764,305841
Providence,41.8236,-71.4222,177994
"))
leaflet(cities) %>%
addProviderTiles(providers$OpenStreetMap) %>%
# these markers will appear on your map:
addCircleMarkers(
lng = ~Long, lat = ~Lat, weight = 1, fillOpacity = 0.5,
radius = ~sqrt(Pop)/50, popup = ~City, label = ~City,
group ='circles' # group needs to be different than addMarkers()
) %>%
addResetMapButton() %>%
# these markers will be "invisible" on the map:
addMarkers(
data = cities, lng = ~Long, lat = ~Lat, label = cities$City,
group = 'cities', # this is the group to use in addSearchFeatures()
# make custom icon that is so small you can't see it:
icon = makeIcon(
iconUrl = "http://leafletjs.com/examples/custom-icons/leaf-green.png",
iconWidth = 1, iconHeight = 1
)
) %>%
addSearchFeatures(
targetGroups = 'cities', # group should match addMarkers() group
options = searchFeaturesOptions(
zoom=12, openPopup = TRUE, firstTipSubmit = TRUE,
autoCollapse = TRUE, hideMarkerOnCollapse = TRUE
)
) %>%
addControl("<P><B>Hint!</B> Search for ...<br/><ul><li>New York</li>
<li>Boston</li><li>Hartford</li><li>Philadelphia</li><li>Pittsburgh</li>
<li>Providence</li></ul></P>",
position = 'bottomright'
)
I was having this issue, and found a solution on the leaflet.extras Github issues page.
In your installation of leaflet.extras:
Open lfx-search-prod.js and search for "e instanceof t.Path ||" , and then delete it and save the file. Your CircleMarker search should work now
This should allow you to use addSearchFeature() with addCircleMarkers() without any workaround now.

multiple copies of the world when zooming out in worldmap created with leaflet in R

I am using the leaflet library in R and I am creating a world map with the following code:
leaflet(data = sPDF) %>%
addProviderTiles("Stamen.Watercolor") %>%
addPolygons(fillColor = ~pal(sPDF$Colonizer_col),
fillOpacity = 0.8,
color = "#BDBDC3",
weight = 1,
popup = state_popup) %>%
addLegend("bottomright", pal = pal, values = ~na.omit(Colonizer),
title = "Colony Information",
labFormat = labelFormat(prefix = ""),
opacity = 1 ) %>%
addCircles(data=left, lng = ~LONG, lat = ~LAT, weight = 1,
radius = ~sqrt(Totals)*300, popup = ~area_popup_left) %>%
addCircles(data=arrived, lng = ~LONG, lat = ~LAT, weight = 1,
radius = ~sqrt(Totals)*300, popup = ~area_popup_arrive, fillColor = "Green" )%>%
setView(lng = -1.5, lat = 53.4, zoom = 2.5)#%>%# set centre and extent of map
When the map shows up in R it is all fine but when I export it to an .html file it allows the user to zoom out so much that there is three copies of the world map.
I would like to set it so that the maximum zoom out allows only one copy of the map as a webpage (the same way as it is presented in R).
I have tried
tileOptions(maxZoom=5)
but this only affects the zoom while the map is viewed in R, not when it is exported to html.
Leaflet's L.Map class has an option to stop the copying of the map's overlays:
With this option enabled, the map tracks when you pan to another "copy" of the world and seamlessly jumps to the original one so that all overlays like markers and vector layers are still visible.
http://leafletjs.com/reference.html#map-worldcopyjump
The proper way of making sure a user doesn't pan out a certain area is using L.Map's maxBounds option:
When this option is set, the map restricts the view to the given geographical bounds, bouncing the user back when he tries to pan outside the view.
http://leafletjs.com/reference.html#map-maxbounds
In code:
leafletMap(
"map", "100%", "100%",
initialTileLayer = "http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
initialTileLayerAttribution = HTML('© OpenStreetMap contributors, © CartoDB'),
options=list(
center = c(0, 0),
zoom = 0,
worldCopyJump = FALSE,
maxBounds = list(
list(-90, -180),
list(90, 180)
)
)
)
You could indeed top that off with setting the noWrap option on your L.TileLayer but all that in fact does is stop the tiles from repeating which is imo not the solution to your actual problem:
If set to true, the tiles just won't load outside the world width (-180 to 180 longitude) instead of repeating.
http://leafletjs.com/reference.html#tilelayer-nowrap

Change color of leaflet marker

Is there anyway to change the color of leaflet marker base on the value of some variable. In the following map, for example, I wish to assign marker color based on mag variable:
library(leaflet)
data(quakes)
# Show first 20 rows from the `quakes` dataset
leaflet(data = quakes[1:20,]) %>% addTiles() %>%
addMarkers(~long, ~lat, popup = ~as.character(mag))
I often use the circle markers because you can change both the size and color based on other variables. For example, I have created a binned variable from a continuous using the following code:
# first cut the continuous variable into bins
# these bins are now factors
last$BeatHomeLvl <- cut(last$BeatHome,
c(0,.5,1,2,3,5,100), include.lowest = T,
labels = c('<.5x', '.5-1x', '1-2x', '2-3x', '3-5x','5x+'))
# then assign a palette to this using colorFactor
# in this case it goes from red for the smaller values to yellow and green
# standard stoplight for bad, good, and best
beatCol <- colorFactor(palette = 'RdYlGn', last$BeatHomeLvl)
When you plot it, I use the code for circle markers. The radius/area of the circle is based on the actual value of the factor and then color is assigned according to the bins.
m1 <- leaflet() %>%
addTiles() %>%
addProviderTiles(providers$OpenStreetMap, group = 'Open SM') %>%
addProviderTiles(providers$Stamen.Toner, group = 'Toner') %>%
addProviderTiles(providers$Esri.NatGeoWorldMap, group = 'NG World') %>%
setView(lng = -72, lat = 41, zoom = 8) %>%
addCircleMarkers(data = Jun, lat = ~Lat, lng = ~Lon,
color = ~beatCol(BeatHomeLvl), popup = Jun$Popup,
radius = ~sqrt(BeatHome*50), group = 'Home - Jun') %>%
At the end of your code add a legend. I added some formatting.
addLegend('bottomright', pal = beatCol, values = last$BeatHomeLvl,
title = 'Compare Home<br>Quote Count to<br>3Mos State Avg',
opacity = 1)
This gives you color-coded and sized circles based on a variable and a nice legend.
As far as I know, you need to assign an image file to one level of icon. For instance, if you have three levels in magnitude in the earthquake data, you need to create an icon list with three image paths. Then, you can have three different colors in markers. At least, the following example is getting closer to what you want. I edited a png file and created three png files. You need to specify the paths of the file when you make an icon list.
library(dplyr)
library(leaflet)
mutate(quakes, group = cut(mag, breaks = c(0, 5, 6, Inf), labels = c("blue", "green", "orange"))) -> mydf
### I edit this png file and created my own marker.
### https://raw.githubusercontent.com/lvoogdt/Leaflet.awesome-markers/master/dist/images/markers-soft.png
quakeIcons <- iconList(blue = makeIcon("/Users/jazzurro/Documents/Stack Overflow/blue.png", iconWidth = 24, iconHeight =32),
green = makeIcon("/Users/jazzurro/Documents/Stack Overflow/green.png", iconWidth = 24, iconHeight =32),
orange = makeIcon("/Users/jazzurro/Documents/Stack Overflow/orange.png", iconWidth = 24, iconHeight =32))
leaflet(data = mydf[1:100,]) %>%
addTiles() %>%
addMarkers(icon = ~quakeIcons[group])
This one worked for me:
Source: https://github.com/bhaskarvk/leaflet/blob/master/inst/examples/awesomeMarkers.R
library(leaflet)
icon.glyphicon <- makeAwesomeIcon(icon= 'flag', markerColor = 'blue', iconColor = 'black')
icon.fa <- makeAwesomeIcon(icon = 'flag', markerColor = 'red', library='fa', iconColor = 'black')
icon.ion <- makeAwesomeIcon(icon = 'home', markerColor = 'green', library='ion')
# Marker + Label
leaflet() %>% addTiles() %>%
addAwesomeMarkers(
lng=-118.456554, lat=34.078039,
label='This is a label',
icon = icon.glyphicon)
leaflet() %>% addTiles() %>%
addAwesomeMarkers(
lng=-118.456554, lat=34.078039,
label='This is a label',
icon = icon.fa)
leaflet() %>% addTiles() %>%
addAwesomeMarkers(
lng=-118.456554, lat=34.078039,
label='This is a label',
icon = icon.ion)
# Marker + Static Label using custom label options
leaflet() %>% addTiles() %>%
addAwesomeMarkers(
lng=-118.456554, lat=34.078039,
label='This is a static label',
labelOptions = labelOptions(noHide = T),
icon = icon.fa)
Why not use vector markers based on svg (here is one example implementation - https://github.com/hiasinho/Leaflet.vector-markers) that you can apply any fill color you want to? Instead of having to create a large amount of static image files. Some code involved, yes, but a lot more flexible.
L.Marker uses images (one for the marker, one for the shadow) so that's not possible. You can however use your own images, there's a good write up on the topic among the tutorials on the Leaflet site:
http://leafletjs.com/examples/custom-icons.html

Resources