Whenever the mouse pointer is hovering over a leaflet map, the browser does not scroll up or down. This happens even when I affix minZoom and maxZoom to an equal value. Is there a solution to this?
php.poverty.map.2009 <-
leaflet(options = leafletOptions(minZoom = 12, maxZoom = 12)) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(data = php.df.polygon.2009,
fillColor = ~php.pal.2009(percent),
color = "#b2aeae", # must use hex colors
fillOpacity = 0.7,
weight = 0.3,
smoothFactor = 0.2,
popup = php.popup.2009) %>%
addLegend(pal = php.pal.2009,
values = php.df.polygon.2009$percent,
position = "bottomright",
title = "Percent of Households <br> Living below Poverty <br> (Census, 2009)",
labFormat = labelFormat(suffix = "%"))
php.poverty.map.2009
In my second attempt at answering this question I came across the leaflet.extras package which implements a selection of leaflet plugins in R. One of these is the Leaflet.Sleep plugin which can be implemented by adding the suspendScroll() function to your leaflet map in R.
Basic Example
First, install leaflet.extras using devtools::install_github('bhaskarvk/leaflet.extras').
library(leaflet)
library(leaflet.extras)
leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
suspendScroll()
See this page for an example.
A Leaflet map has a documented scrollWheelZoom option that allows you to disable scrollwheel interactions (but still allows other ways to zoom the map, such as the zoom buttons).
In plain Javascript, this is used like var map = L.map({ scrollWheelZoom: false }). I'm not well versed in R, but you should try leaflet(options = leafletOptions(scrollWheelZoom = false)) or variations thereof.
I think your zoom options might need to go in the providerTiles function. I.e. addProviderTiles("CartoDB.Positron", options = providerTileOptions(minZoom=12, maxZoom=12))
Related
Anyone created a leaflet map in Code Workbook using r-Leaflet? I have a functioning script that runs (also double checked in R) but how do I get it to visualise and then use in a Report etc. I have tried various tweaks on what may get it to run but no success - any ideas
leaflet_map <- function(map_data) {
library(leaflet)
data<-map_data
# first cut the continuous variable into bins
# these bins are now factors
data$Fill_rateLvl <- cut(data$Fill_rate,
c(0,.5,0.6,0.7,0.8,0.9,1), include.lowest = T,
labels = c('<50%', '50-60%', '60-70%', '70-80%', '80-90%','90-100%'))
# 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
FillCol <- colorFactor(palette = 'RdYlGn', data$Fill_rateLvl)
m<-leaflet() %>%
addTiles() %>%
addProviderTiles(providers$CartoDB.Positron)%>%
setView(lng = -0, lat = 50, zoom = 8) %>%
addCircleMarkers(data = data, lat = ~lat, lng = ~long,
color = ~FillCol(Fill_rateLvl), popup = data$Lead_employer,
radius = ~sqrt(Fill_rate*50), group = 'Fill rate') %>%
addLegend('bottomright', pal = FillCol, values = data$Fill_rateLvl,
title = 'Fill rate for next two weeks',
opacity = 1)
return(NULL)
}
I am not familiar with R in code workbook, but it sounds to me that you need to materialize your leaflet map as a dataset and then consume it in some sort of map compatible UI.
For example slate has a map widget which is backed by leaflets. You can find documentation and examples for it in https://www.palantir.com/docs/foundry/slate/widgets-map/
I've built the following app https://iseak.shinyapps.io/Mapa/
and I would like to switch from tmap to leaflet for the map portion of the app because I've run into some limitations (I'd like fancier popups and some other stuff).
Currently the map is working with tmap using the following code:
output$map = renderLeaflet({
tm <- tm_shape(subsetData()) +
tm_fill(selvar(), palette=colores(),
alpha=0.95,
breaks=breaks(),
id="Zona",
popup.vars=c(" "="popover"),
popup.format=list(digits=2),
legend.show = F,
labels=c(" "=selvar())
) +
tm_borders() +
tmap_options(basemaps = "CartoDB.Positron"
)
tmap_leaflet(tm) %>%
removeLayersControl()
})
My starting point when trying to use leaflet directly is:
output$map = renderLeaflet({
leaflet(data=subsetData()) %>%
addProviderTiles("CartoDB.Positron") %>%
clearShapes() %>%
clearControls() %>%
addPolygons(data = subsetData(),
fillColor = ~colores()(selvar()),
fillOpacity = 0.9,
weight = 2)
})
But I keep getting errors. I would appreciate some pointers on how to easily switch from tmap to leaflet and how to use reactive values inside the leaflet call. Thanks!
This question is quite open. I think the leaflet website has quite good example code (https://rstudio.github.io/leaflet/). Browse through the left menu.
When it come to reactivity you don't need brackets to use variable created by reactiveValues; in case of reactive() you need some.
Looking at your code I'm not sure what is behind color() and selvar(). Assuming selvar() is the number for the color scale my approach would have been something like this:
selvar <- reactiveValues(n=c(1:10)
output$map = renderLeaflet({
pal <- leaflet::colorBin(brewer.pal(9,"Blues"), domain = selvar, bins = 7, na.color = "gray")
leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(data=shp,
fillColor = ~pal(selvar),
fillOpacity = 0.9,
weight = 2)
You can specify your shape data in leaflet() or in addPolygons(). Using the latter allows to use different shape file tables. Finally, another useful pointer is leafletProxy('map') which would work well with the year buttons underneath the map for fast updates.
I'm building an interactive map in Leaflet using R, and I would like to use the Leaflet.MarkerCluster.PlacementStrategies sub-plugin to control the placement of markers within a cluster (when "spiderfied" on mouse click over the cluster), and always lay them out in a circle around the cluster icon, rather than along a spiral as it happens when there are more than 8 markers in a cluster with the standard Leaflet.MarkerCluster plugin that comes embedded in the leaflet htmlWidget. The code I'm using to build the map is something like this:
library(leaflet)
data_example <- data.frame(name = rep("site A", times = 14),
lon = rep(14.25000, times = 14),
lat = rep(40.83333, times = 14),
issue = paste("Issue", LETTERS[1:14]),
severity = sample(c("Mild", "Moderate", "Severe"), size = 14, replace = TRUE))
issues_pal <- colorFactor(brewer.pal(3, "RdYlBu"), levels = c("Mild", "Moderate", "Severe"), reverse = TRUE)
leaflet(data_example, options = leafletOptions(maxZoom = 7)) %>%
setView(lng = 8, lat = 50, zoom = 4) %>%
addProviderTiles(providers$Esri.WorldStreetMap) %>%
addCircleMarkers(
lng = ~ lon,
lat = ~ lat,
radius = 10,
color = "grey",
weight = 2,
fillColor = ~ issues_pal(severity),
#stroke = FALSE,
fillOpacity = 0.8,
label = ~ paste(issue, severity),
clusterOptions = markerClusterOptions(
spiderfyDistanceMultiplier = 1.1,
spiderLegPolylineOptions = list(weight = 0)),
group = df,
clusterId = df
)
In the map, when one clicks on the cluster icon, the markers are shown placed along a spiral path originating from the cluster. This is because the Leaflet.MarkerCluster plugin that control the clustering of markers in leaflet, place them along a circle only when there are up to 8 markers. But the Leaflet.MarkerCluster.PlacementStrategies should allow to specify a different placement strategy, and to have markers laid out in a circle even if they are more than 8, as shown in this page and here.
Since the sub-plugin is not yet included in leaflet package, I'd like to use the method highlighted here to use in R any leaflet JS plugins, but I'm struggling to find a way to make it work for my case. According to the method, I should first of all include the following in my code:
placement.strategies <- htmlDependency(
"Leaflet.MarkerCluster.PlacementStrategies",
"0.0.1",
src = c(href = "https://github.com/adammertel/Leaflet.MarkerCluster.PlacementStrategies/blob/master/dist/"),
script = "leaflet-markercluster.placementstrategies.src.js"
)
registerPlugin <- function(map, plugin) {
map$dependencies <- c(map$dependencies, list(plugin))
map
}
And then I should call registerPlugin(placement.strategies) in the leaflet pipe. However, I can't figure out how to adapt the following custom JS code to my needs:
leaflet() %>% setView(lng = 8, lat = 50, zoom = 4) %>%
# Register plugin on this map instance
registerPlugin(placement.strategies) %>%
# Add your custom JS logic here. The `this` keyword
# refers to the Leaflet (JS) map object.
onRender("function(el, x) {
L.esri.basemapLayer('Topographic').addTo(this);
}")
I've tried to simply specify in the call to addCircleMarkers() the elementsPlacementStrategy = 'one-circle' as a clusterOption within the markerClusterOptions(), but it does not work. I suspect the JS code I need to call from should somehow modify the option property elementsPlacementStrategy for the cluster, but how to do that I don't know. Can anyone help with this? Thank you in advance!
post scriptum
I have found a way around to get the circle placement without using the subplugin, that involves modifying in the leaflet.markercluster.js file the _circleSpiralSwitchover property to a number greater than 14 (that is the number of markers I have in the cluster). While this workaround achieves the result I wanted, it is sub-optimal, because unless I decide to modify the default .js file that is located in:
/Library/Frameworks/R.framework/Versions/3.2/Resources/library/leaflet/htmlwidgets/plugins/Leaflet.markercluster
I would need to remake the edit on the .js file every time I export the map with saveWidget.
I have a map in leaflet in RShiny which have markers plotted and once I click a marker it adds circles to map showing all the related points to the marker.
What I want to do is to set zoom/view of the map in such a way that all the related circles are visible.
The number of circles varies as per markers i.e. some marker have 1 or 2 circles while some have more. Also, the location of circles varies across the USA so they can be placed in one city or another state.
Following is the code I am using to add circles to existing map
proxy <-leafletProxy("map",data = df)%>%
clearMarkers()%>%
addCircleMarkers(lat = ~lat,lng = ~lng,layerId = ~circle_pt,fillColor =
'green',opacity = 0.5,color = 'red',fillOpacity = 1)%>% clearPopups()%>%
addPopups(lat=~lat,lng=~lng,~as.character(circle_pt))
map=original map with markers
df=lat lng of circles with associated properties of selected marker in map
I want to set zoom level as shown in figure 2.
Kindly help me to identify how to calculate optimal zoom level in leaflet in shiny.
Regards,
If you want to set your initial view, you can use:
setView(lng, lat, zoom = zoom_level)
which is straight from the documentation.
Unless you provide more information, nobody will be able to understand the part where you're saying "in such a way that all the related circles are visible."
I'm not sure how you're app works and whats in the original call to leaflet. But maybe the following example might help you.
I store the click on the markers, filter the data according to the clicked layerId, get the min/max lat/long of the resulting data and then use fitBounds() to set the "zoom" level. (You could also use flyToBounds with the same arguments, which should make a smoother transition to the selected markers, but its still too buggy for me at least)
library(shiny)
library(shinyjs)
library(leaflet)
cords <- data.frame(
lng = runif(100, 14, 18),
lat = runif(100, 54, 58),
circle_pt = sample(1:20, size = 100, replace = T)
)
ui <- fluidPage(
leafletOutput("map", height = "700px")
)
server <- function(input, output, session) {
output$map <- renderLeaflet({
leaflet(data = cords) %>%
addTiles() %>%
addCircleMarkers(lat = ~lat,lng = ~lng, layerId = ~circle_pt, fillColor = 'green',
opacity = 0.5,color = 'red',fillOpacity = 1)
})
observeEvent(input$map_marker_click, {
clickid = input$map_marker_click$id
cordsNew = cords[cords$circle_pt==clickid,]
maxLong = max(cordsNew$lng)
maxLat = max(cordsNew$lat)
minLong = min(cordsNew$lng)
minLat = min(cordsNew$lat)
proxy <-leafletProxy("map", data = cordsNew)
proxy %>%
addCircleMarkers(lat = ~lat,lng = ~lng, layerId = ~circle_pt, fillColor = 'green',
opacity = 0.5,color = 'red',fillOpacity = 1) %>%
fitBounds(minLong,minLat,maxLong,maxLat) %>%
clearPopups() %>%
addPopups(lat=~lat,lng=~lng,~as.character(circle_pt))
})
}
shinyApp(ui = ui, server = server)
may be you can define an interval varint <- findInterval() and that pass to setView
varint <- findInterval()
setView(lng= lng,lat = lat, zoom = varint)
in findInterval, try to put some range of data with the distance between all points
EDIT:
try to calculate the distance between the farthest points that appear.
proxy <-leafletProxy("map",data = df) %>%
setView(
lng = click$lng,
lat=click$lat,
zoom=findInterval(someaverageofyourpoints, c(25,75,100,250,400,750,1000))
)
you can sum other values to findinterval, findinterval()+ 1 .. 2.. 4 ...5 for setting zoom level if findintervalset a tiny value
I want to use static labels in my leaflet markers but I do not want the white background that shows with the labels. Is it possible to show only the text without the white background.
library(leaflet)
temp=data.frame(lng=c(-90,-100),lat=c(30,35))
leaflet(temp) %>% addTiles() %>%
addCircleMarkers(~lng,~lat)%>%
addPopups(~lng, ~lat,'<b>Hello, world</b>!',
options = popupOptions(minWidth = 20, closeOnClick = FALSE, closeButton = FALSE))
Adding label in addMarkers solved my problem.
library(leaflet)
temp=data.frame(lng=c(-90,-100),lat=c(30,35))
leaflet(temp) %>% addTiles() %>%
addMarkers(data=temp, ~lng,~lat,
label=~as.character(lat),
labelOptions = labelOptions(noHide = T,
textOnly = T,textsize = "28px",offset = c(12, -5)))
Yes, but you will find that it works with various degrees of success right out of the Github box. But is it pretty straight forward. You will want to use this and then with the labels setOpacity. It will affect both markers and labels.
Here is the link to a pluggin you need:
Leaflet R Pluggin & directions