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.
Related
I have this map in leaflet/r:
library(leaflet)
library(leaflet.extras)
library(dplyr)
# using the same reproducible data from the question/example
cities <- na.omit(read.csv(
textConnection("City,Lat,Long,Pop, term1, term2
Boston,42.3601,-71.0589,645966, AAA, BBB
Hartford,41.7627,-72.6743,125017, CCC, DDD
New York City,40.7127,-74.0059,8406000, EEE, FFF
Philadelphia,39.9500,-75.1667,1553000, GGG, HHH
Pittsburgh,40.4397,-79.9764,305841, III, JJJ
Providence,41.8236,-71.4222,177994, JJJ, LLL
")))
# leaf-green.png
#https://leafletjs.com/examples/custom-icons/leaf-green.png
leaflet(cities) %>%
addProviderTiles(providers$OpenStreetMap) %>%
addMarkers( clusterOptions = markerClusterOptions()) %>%
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 = "https://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
)
)
Using this map, I am able to "search" for a city using the search bar:
I would like to modify this code so that I can search based on "city", "term1" or "term2".
I tried this code over here:
leaflet(cities) %>%
addProviderTiles(providers$OpenStreetMap) %>%
addMarkers( clusterOptions = markerClusterOptions()) %>%
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 = "https://leafletjs.com/examples/custom-icons/leaf-green.png",
iconWidth = 1, iconHeight = 1
)
) %>%
addSearchFeatures(
targetGroups = c('cities', 'term1', 'term2'), # group should match addMarkers() group
options = searchFeaturesOptions(
zoom=12, openPopup = TRUE, firstTipSubmit = TRUE,
autoCollapse = TRUE, hideMarkerOnCollapse = TRUE
)
)
This code runs without error, but I can not search using "term1" or "term2":
According to the documentation (https://www.rdocumentation.org/packages/leaflet.extras/versions/1.0.0/topics/addSearchFeatures), "addSearchFeatures" should accept a "vector of group names of groups whose features need to be searched". I was under the impression that vectors in R are specified using c('arg1', 'arg2', 'arg3') - but apparently in this function, this is not the case?
Could someone please show me how to fix this?
Thank you!
For the element to be a search term in addSearchFeatures, I'm pretty sure that it has to be a group element. Check it out:
leaflet(cities) %>%
addProviderTiles(providers$OpenStreetMap) %>%
addMarkers(clusterOptions = markerClusterOptions()) %>%
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 = "https://leafletjs.com/examples/custom-icons/leaf-green.png",
iconWidth = 1, iconHeight = 1
)) %>%
addMarkers(data = cities, lng = ~Long, lat = ~Lat,
label = cities$term1, group = 'term1') %>%
addMarkers(data = cities, lng = ~Long, lat = ~Lat,
label = cities$term2, group = 'term2') %>%
addSearchFeatures(
targetGroups = c('cities', 'term1', 'term2'), # group should match addMarkers() group
options = searchFeaturesOptions(
zoom=12, openPopup = TRUE, firstTipSubmit = TRUE,
autoCollapse = TRUE, hideMarkerOnCollapse = TRUE
)
)
Anybody know how to set a default layer to show just one Overlay group first rather than all at once? For example, in the following if I just wanted to show 'Mex' initially and then let the viewer swap to 'GTM'?
library(raster)
library(leaflet)
#load in shapefiles
gtm <- getData('GADM', country = 'GTM', level = 0)
mex <- getData('GADM', country = 'MEX', level = 0)
leaflet() %>%
addTiles() %>%
addPolygons(data = gtm,
fillColor = 'red',
group = "gtm") %>%
addLegend(color = "red",
labels = gtm#data$GID_0,
group = "gtm") %>%
addPolygons(data = mex,
fillColor = 'blue',
group = "mex") %>%
addLegend(color = "blue",
labels = mex#data$GID_0,
group = "mex") %>%
addLayersControl(overlayGroups = c("gtm", "mex"),
options = layersControlOptions(collapsed = F),
)
Use function hideGroup to hide groups from code
addLayersControl(overlayGroups = c("gtm", "mex"),
options = layersControlOptions(collapsed = F)) %>%
hideGroup("mex")
See the official leaflet vignette under section Show/Hide Layers
In the following code, I would like to have a control button to initiate and stop the following events:
turns all overlayGroups off,
then turns the 1st overlayGroup on for 1 second
then turns all overlayGroups off for 1 second
then turns the 2nd overlayGroup on for 1 second
cycles until stopped.
library(leaflet)
icon.Union <- makeAwesomeIcon(icon = "chevron-down",
markerColor = "lightblue",
iconColor="#FFFF33",
library = "fa")
icon.Confederacy <- makeAwesomeIcon(icon = "chevron-down",
markerColor = "lightgray",
iconColor="#FFFFFF",
library = "fa")
lng = -98.5795;lat = 39.8283
leaflet() %>%
addTiles(group = "OSM") %>%
setView(lng,lat, zoom = 4.0) %>%
addAwesomeMarkers(
lng = -77.23667, lat = 39.80861,
label = "Gettysburg, PA",
group = "Union",
icon = icon.Union) %>%
addAwesomeMarkers(
lng = -88.32183, lat = 35.15068,
label = "Shiloh, TN",
group = "Union",
icon = icon.Union) %>%
addAwesomeMarkers(
lng = -79.8747, lat = 32.7523,
label = "Fort Sumter",
group = "Confederacy",
icon = icon.Confederacy) %>%
addLayersControl(baseGroups="OSM",
overlayGroups = c("Union", "Confederacy"),
options= layersControlOptions(collapsed=TRUE))
I want to avoid requiring repetitive clicking on radio buttons to accomplish this.
Any suggestion will be greatly appreciated.
I posted a similar question here:
How do I create a Leaflet Proxy in observeEvent() for checkboxGroup in R Shiny .
But I'm a little desperate for answers, so I thought I'd rephrase my question and post it again. I've scoured the internet for answers and can't seem to find what I'm looking for. Apologies for the double posting.
Here's my issue.
I have a dataset here:
https://github.com/mallen011/Leaflet_and_Shiny/blob/master/Shiny%20Leaflet%20Map/csv/RE.csv
It's recycling centers in Kentucky. It's set up so each recyclable material is a column, and each row i.e. recycling center is listed as yes/no as to whether each center actually recycles said material.
Here's an example of what the data looks like, in case you can't access the csv. Top row is the header column. Sorry for the formatting:
Name___________________GL______AL_____PL
Bath Community Recycling___Yes_____No____Yes
Ted & Sons Scrap Yard______No______No____Yes
Now I have the csv visualized on a R shiny dashboard app like here using Leaflet:
https://github.com/mallen011/Leaflet_and_Shiny/blob/master/Shiny%20Leaflet%20Map/re_map.png
But I want to add a control in which users can filter through where they can recycle their goods, namely, I want to use checkboxGroupInput() in R shiny so users can check materials and have recycling centers populate the map. For example, if a person wants to know where to recycle their glass, they can check "glass" in the checkbox group, and all recycling centers that allow glass recycling pop up.
So in R Shiny, I've read my recycling data csv (RE.csv):
RE <- read.csv("C:/Users/username/Desktop/GIS/Shiny Leaflet Map/csv/RE.csv")
RE$y <- as.numeric(RE$y)
RE$x <- as.numeric(RE$x)
RE.SP <- SpatialPointsDataFrame(RE[,c(7,8)], RE[,-c(7,8)])
Here's my UI that puts the checkboxGroupInput() in the sidebar():
ui <- dashboardPage(
skin = "blue",
dashboardHeader(titleWidth = 400, title = "Controls"),
dashboardSidebar(width = 400
#here's the checkboxgroup, it calls the columns for glass, aluminum and plastic from the RE.csv, all of which have binary values of yes/no
checkboxGroupInput(inputId = "RE_check",
label = h3("Recycleables"),
choices = list("Glass" = RE$GL, "Aluminum" = RE$AL, "Plastic" = RE$PL),
selected = 0)
),
dashboardBody(
fluidRow(box(width = 12, leafletOutput(outputId = "map"))),
tags$style(type = "text/css", "#map {height: calc(100vh - 80px) !important;}"),
leafletOutput("map")
)
)
And now for the trouble I'm having: What do I put into my server so it observes each of these events?
This is what I have for the event in which a user checks "glass", and I have no idea how wrong or how right it is. I just know it's not working. I'm trying to use "if" statements, so only values that equal "yes" populate the map. But currently, the map in the dashboard is blank no matter what I do, although the checkbox group input seems to work.
server <- function(session, input, output) {
observeEvent({
RE_click <- input$map_marker_click
if (is.null(RE_click))
return()
if(input$RE$GL == "Yes"){
leafletProxy("map") %>%
clearMarkers() %>%
addMarkers(data = RE_click,
lat = RE$y,
lng = RE$x)
return("map")
}
})
Here's my output leaflet map too, in case that matters:
output$map <- renderLeaflet({
leaflet() %>%
setView(lng = -83.5, lat = 37.6, zoom = 8.5) %>%
addProviderTiles("Esri.WorldImagery") %>%
addProviderTiles(providers$Stamen.Toner, group = "Toner") %>%
addPolygons(data = counties,
color = "green",
weight = 1,
fillOpacity = .1,
highlight = highlightOptions(
weight = 3,
color = "green",
fillOpacity = .3)) %>%
addMarkers(data = RE,
lng = ~x, lat = ~y,
label = lapply(RE$popup, HTML),
group = "recycle",
clusterOptions = markerClusterOptions(showCoverageOnHover = FALSE)) %>%
addLayersControl(baseGroups = c("Esri.WorldImagery", "Toner"),
overlayGroups = c("recycle"),
options = layersControlOptions(collapsed = FALSE))
})
}
I'm new to R Shiny if that's not obvious. I'd really appreciate any and all help.
All my code is publicly available on my GitHub for download:
https://github.com/mallen011/Leaflet_and_Shiny
Thanks and stay safe!
Maybe this would work... You can add the different recycle types as layers, then add the checkboxes on the leaflet map instead of worrying about shiny integration. Obviously, you'd have to add the rest of your recycle types on here...
library(leaflet)
library(htmlTable)
RE <- read.csv("https://raw.githubusercontent.com/mallen011/Leaflet_and_Shiny/master/Shiny%20Leaflet%20Map/csv/RE.csv")
leaflet() %>%
setView(lng = -83.5, lat = 37.6, zoom = 8.5) %>%
addProviderTiles("Esri.WorldImagery") %>%
addProviderTiles(providers$Stamen.Toner, group = "Toner") %>%
# addPolygons(data = counties,
# color = "green",
# weight = 1,
# fillOpacity = .1,
# highlight = highlightOptions(
# weight = 3,
# color = "green",
# fillOpacity = .3)) %>%
addMarkers(data = RE[RE$AL=="Yes", ],
lng = ~x, lat = ~y,
#label = lapply(RE$popup, HTML),
group = "AL",
clusterOptions = markerClusterOptions(showCoverageOnHover = FALSE)) %>%
addMarkers(data = RE[RE$FE=="Yes", ],
lng = ~x, lat = ~y,
#label = lapply(RE$popup, HTML),
group = "FE",
clusterOptions = markerClusterOptions(showCoverageOnHover = FALSE)) %>%
addMarkers(data = RE[RE$NONFE=="Yes", ],
lng = ~x, lat = ~y,
#label = lapply(RE$popup, HTML),
group = "NONFE",
clusterOptions = markerClusterOptions(showCoverageOnHover = FALSE)) %>%
addLayersControl(baseGroups = c("Esri.WorldImagery", "Toner"),
overlayGroups = c("AL", "FE", "NONFE"),
options = layersControlOptions(collapsed = FALSE))
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