How do I add polygons from Global Administrative areas, so they are clickable.
The simple way describe in the docs that I tried is
adm <- getData('GADM', country='UKR', level=1)
leaflet() %>% addTiles() %>% addPolygons(data=adm, weight = 3, fillColor = col)
But imagine I want a leaflet map that will have onClick actions later.
Based on SuperZip, I need to have something similar to
map <- createLeafletMap(session, "map")
session$onFlushed(once=TRUE, function() {
map$addPolygon(...)
})
However, there is no addPolygon method and I am confused how will it work for SpartialPolygons.
I also tried converting to geoJSON, similar to https://ropensci.org/blog/2013/10/23/style-geojson-polygon/ or this SO question, but doing
polys <- fromJSON(<json data file>)
map <- createLeafletMap(session, "map")
session$onFlushed(once=TRUE, function() {
map$geoJson(polys)
})
Gives me an error
Error in func() : attempt to apply non-function
Is there a way to do it? Or what am I doing wrong?
I am not sure I really understand the problem, although I read through the question a couple of times. However the code below seems to work for me, as it can easily be combined with a simple onClick event, like a pop up displaying the name of each adm. unit:
---
title: "Ukraine"
runtime: shiny
output: html_document
---
```{r, echo=FALSE, message=F, warning=F}
library(leaflet)
library(raster)
adm <- getData('GADM', country='UKR', level=1)
popup <- paste0("<strong>Name: </strong>",
adm$NAME_1)
leaflet() %>%
addTiles() %>%
addPolygons(data=adm, weight = 2, fillColor = "yellow", popup=popup)
```
Related
I was looking into this repo, where a blue dot is added to your leaflet map, that if you open it on a phone, it follows you as you walk, similar to a google maps option, as shown in this demo.
Usually in R and using Rmd, I would have this code so that I can know where I am on the map:
title: "Test map"
output: html_document
knitr::opts_chunk$set(echo = TRUE)
library(leaflet)
Old map.locate option
I usually made this maps for the field
leaflet() %>%
addTiles() %>%
setView(-71.0382679, 42.3489054, zoom = 18) %>%
addEasyButton(easyButton(
icon="fa-crosshairs", title="Locate Me",
onClick=JS("function(btn, map){ map.locate({setView: true, enableHighAccuracy: true }); }")))
That works great for finding your location, but it does not generate a marker where you are, and more importantly, it does not follow you around, you can see an example of that here
Trying to incorporate control.locate
So my first try was just to change locate for control.locate, but that did not work.
leaflet() %>%
addTiles() %>%
setView(-71.0382679, 42.3489054, zoom = 18) %>%
addEasyButton(easyButton(
icon="fa-crosshairs", title="Follow Me",
onClick=JS("function(btn, map){ map.control.locate()}")))
I am still thinking of other options, but any help would be welcome, here is the full rmd in github
These GPS features have been implemented in the leaflet.extras package.
Here's a working version based on your MWE
library(leaflet)
library(leaflet.extras)
your_map <- leaflet() %>%
addTiles() %>%
setView(-71.0382679, 42.3489054, zoom = 18) %>%
addControlGPS(
options = gpsOptions(
position = "topleft",
activate = TRUE,
autoCenter = TRUE,
setView = TRUE))
activateGPS(your_map)
The results looks like this:
Spoiler: Chrome thinks I'm in São Paulo right now... (where I'd rather be!)
...and here's a working demo on my Git.
Work's like a charm on my mobile.
Intro:
I am trying to embed a leaflet map into a revealjs presentation within an RMarkdown file. My example below is pretty close, but it is (1) missing tiles, (2) the popups are not displaying, and (3) the legend and font are way too big!
I am not too concerned with how the code blocks look at the moment. I'm planning on using the results = "hide" slide option for my final product.
Thanks in advance!
Reproducible Example:
---
title: "My Presentation"
author: Me
date: 2017-06-23
output:
revealjs::revealjs_presentation:
theme: black
---
## Loading in necessary packages:
```{r}
library(dplyr)
library(sp)
library(rgdal)
library(rgeos)
library(RColorBrewer)
library(classInt)
library(leaflet)
library(htmlwidgets)
```
## Defining our data:
```{r}
lat <- c(45.51158000, 45.50431159, 45.496539)
lon <- c(-122.548056, -122.54775, -122.54788)
no2 <- c(17.37, 25.61, 24.69)
dta <- data.frame(lat, lon, no2)
colnames(dta) <- c("lat","lon","no2")
```
## Create layer of spatial points:
```{r}
points <- SpatialPointsDataFrame(data.frame(x=dta$lon, y=dta$lat), data = data.frame(dta$no2))
plotclr <- (brewer.pal(7, "RdYlGn"))
class <- classIntervals(dta$no2, n = 7, style = "fixed", fixedBreaks = c(0,5,10,15,20,25,30))
colcode <- findColours(class, rev(plotclr))
plot(points, col=colcode, pch=19)
pop1<-paste0("<b>NO2:</b> ", dta$no2, " ppb",
"<br /> <b>Lat:</b> ", dta$lat,
"<br /> <b>Lon:</b> ", dta$lon)
```
## Creating the leaflet map:
```{r}
no2_map <-leaflet()%>%
addTiles('http://{s}.tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png') %>%
addCircleMarkers(data=points, color = "black", radius = dta$no2, fillColor = colcode, fillOpacity=0.7, weight=1, popup=pop1) %>%
addLegend(position = "bottomright", colors = rev(plotclr), labels = rev(c("30","25","20","15","10","5","0")), opacity = 0.9, title = "NO2 (ppb)")
```
---
```{r}
no2_map
saveWidget(no2_map, file="map.html")
```
Unfortunately, reveal.js and Leaflet don't play very well together, and the slide with your maps might be missing layers. This is due to Leaflet not being able to discern the size of the DOM element which serves as the container of the map, because reveal.js resizes all elements dinamically.
The easiest workaround is to just refresh the page when you're in a slide with a Leaflet map. You can also try a deferred call to map.invalidateSize() (by using setTimeout() in plain Javascript)
Running into issues syncing two leaflet maps on different tabs.
After looking at previous entries (Synchronizing two leaflet maps in R / Rmarkdown), the solution provided by #TimSalabim does not work because the maps are on different tabs.
Here is a MWE RMarkdown example:
---
title: "QuestionforStackOverflow"
output:
flexdashboard::flex_dashboard:
runtime: shiny
---
```{r setup, include=FALSE}
library(flexdashboard)
library(shiny)
library(leaflet)
```
Tab One
======================================================================
```{r tab1}
output$map1 <-
renderLeaflet(
leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
setView(-93.65, 42.0285, zoom = 4)
)
leafletOutput("map1")
```
Tab Two
======================================================================
```{r tab2}
output$map2 <-
renderLeaflet(
leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
setView(-93.65, 42.0285, zoom = 4)
)
leafletOutput("map2")
```
I want a two way change. Any view changes to map1 -- changes map2 OR any changes to map2 will change map1.
Ideally: if you scroll into St. Louis on map1, map2 will have the same zoom level on St. Louis.
Right now, there is no interactivity between the two maps. Is there a way to make them sync?
You can use the leafletProxy() for this :
See the help here : https://rstudio.github.io/leaflet/shiny.html
For your particular problem, here's an idea :
---
title: "QuestionforStackOverflow"
output:
flexdashboard::flex_dashboard:
runtime: shiny
---
```{r setup, include=FALSE}
library(flexdashboard)
library(shiny)
library(leaflet)
```
Tab One
======================================================================
```{r tab1}
output$map1 <-
renderLeaflet(
leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
setView(-93.65, 42.0285, zoom = 4)
)
actionButton("syncMap1", "Fit to map2 bounds")
leafletOutput("map1")
observeEvent(input$syncMap1,{
map2coords <- input$map2_bounds
map1Proxy <- leafletProxy("map1")
map1Proxy %>% fitBounds(lng1 = map2coords$east,
lat1 = map2coords$north,
lng2 = map2coords$west,
lat2 = map2coords$south)
})
```
Tab Two
======================================================================
```{r tab2}
output$map2 <-
renderLeaflet(
leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
setView(-93.65, 42.0285, zoom = 4)
)
actionButton("syncMap2", "Fit to map1 bounds")
leafletOutput("map2")
observeEvent(input$syncMap2,{
map1coords <- input$map1_bounds
map2Proxy <- leafletProxy("map2")
map2Proxy %>% fitBounds(lng1 = map1coords$east,
lat1 = map1coords$north,
lng2 = map1coords$west,
lat2 = map1coords$south)
})
```
The idea is to retrieve the coordinates of the other map when clicking on the buttons, and to sync the view then.
Minor problem : the view is not that well synced : could be better to find the centroid of the displayed map and to use setView() using input$map1_zoom.
Major problem : this means using buttons, what is not that user-friendly.
Theoritically, you could use an observe() block to reflect the coordinates of each map to the other. Tried it and it's quite buggy, probably because of some "infinite" loop as there are micro-variations in the coordinates.
No idea how that would work with R, but with plain JavaScript you could use Leaflet.Sync to synchronize two maps.
If you have two tabs of which only one is visible at the time, you could also just sync on tab switch, which is much simpler to implement.
I am trying to display several zipcodes (thus polygons...) on a leaflet map. Data is available as a geojson file here. I chose as an example some zip codes from Seattle.
I tried the following (reproducible example):
library(jsonlite)
library(leaflet)
url <- "https://raw.githubusercontent.com/openseattle/seattle-boundaries/master/data/zip-codes.geojson"
geojson <- fromJSON(url)
map <- leaflet() %>% addTiles() %>% addGeoJSON(geojson)
map
I could not figure out how to properly set addGeoJSON parameters, and calling map only displays the leaflet() %>% addTiles() part...
Documentation is too light for the non json advanced user that I am:
geojson: a GeoJSON list, or character vector of length 1
How should I proceed? Thank you very much in advance for your views on this issue
Regards
You just needed to not parse the geojson to a data.frame, fromJSON(url, FALSE)
library(jsonlite)
library(leaflet)
url <- "https://raw.githubusercontent.com/openseattle/seattle-boundaries/master/data/zip-codes.geojson"
geojson <- fromJSON(url, simplifyVector = FALSE)
leaflet() %>%
addTiles() %>%
addGeoJSON(geojson) %>%
setView(lng = -122.2, lat = 47.6, zoom = 10)
addGeoJSON() will also accept a string, e.g.
geojson_str <- paste0(readLines(url), collapse = "")
then pass that to addGeoJSON
Good afternoon everyone, I think a screenshot will tell better than words:
I would like a real marker instead of what is actually printed...
Here is the corresponding server.R part of the code (where fixed_points is a nrow(fixed_points) x 2 matrix with lat/lon coordinates
library(shiny); library(rCharts); library(leaflet)
output$baseMap <- renderMap({
baseMap <- Leaflet$new()
baseMap$setView(c(lng = 2.812500, lat = 46.732331), zoom = 6)
baseMap$tileLayer(provider = "Stamen.TonerLite")
for (i in 1:nrow(fixed_points)) {baseMap$marker(c(fixed_points[i, "lat"], fixed_points[i, "lon"]))}
baseMap$fullScreen(TRUE)
baseMap
})
and the ui.R
showOutput("baseMap", "leaflet") // or chartOuput(...), it works the same
Thanks in advance!