In my shiny app, I would like to click on a polygon of my mapview map and be able to extract the layerId attribute to a variable using input$map_shape_click
. In the following code, when you click a polygon, it prints out the id, but it is set to null by default in mapview.
library(shiny)
library(tmap)
library(leaflet)
library(mapview)
ui <- bootstrapPage(
title = "Standardized Crop Production Index",
tags$style(type = "text/css", "html, body {width:100%;height:100%}"),
mapview::mapviewOutput("map", width = "100%", height = "100%")
)
data("World") #from the tmap library
server <- function(input, output, session) {
out_plot <- observeEvent(input$map_shape_click, {
p <- input$map_shape_click
print(p)
})
output$map <- renderLeaflet({
test <- mapview(World)
test@map
})
}
shinyApp(ui = ui, server = server)
Is there a way to set the layerId of a mapview object? I know that I could set it using addPolygons()
if I were to just use Leaflet instead of mapview. However, I would eventually like to use the data gathered from clicking the polygon as input into mapview's popupGraph()
.
Even better would be if there is a way to retrieve the attributes from the table that pops up when you click a polygon. For example, if I click on Antarctica, the following attribute table pops up: Antarctica Attribute Table. Is there any way to retrieve the "name" attribute and store it as a variable when a polygon clicked?
A little late, but it is possible to set the layerId
in mapview. mapview will pass any additional (valid) arguments on to the respective leaflet functions via the ...
argument including layerId
. The only difference is that you cannot use the formula notation with mapview as it does only pass the geometry part to (in this case) addPolygons
. So at the time of evaluating the formula, there is no data attached to the geometries and hence it fails. What you can do, though, is pass the respective vector to layerId
.
To sum it up, the following should return the layerId
on input$map_shape_click
:
library(shiny)
library(tmap)
library(leaflet)
library(mapview)
ui <- bootstrapPage(
title = "Standardized Crop Production Index",
tags$style(type = "text/css", "html, body {width:100%;height:100%}"),
mapview::mapviewOutput("map", width = "100%", height = "100%")
)
data("World") #from the tmap library
server <- function(input, output, session) {
out_plot <- observeEvent(input$map_shape_click, {
p <- input$map_shape_click
print(p)
})
output$map <- renderLeaflet({
test <- mapview(World, layerId = World$iso_a3)
test@map
})
}
shinyApp(ui = ui, server = server)
Not entirely sure about your first question, as I'm not aware of any way that can be assigned using mapview()
. However, here is a reproducible solution using addPolygons()
:
library(dplyr)
library(shiny)
library(leaflet)
library(leaflet.extras)
library(rgdal)
library(sp)
library(tigris)
library(htmltools)
setwd(dirname(rstudioapi::getActiveDocumentContext()$path)) # set your working directory
philly <- tracts(state = 'PA', county = c('Philadelphia'))
ui <- fluidPage(
title = "Test Map",
leafletOutput("mymap", width = 600)
)
server <- function(input, output, session) {
RV <- reactiveValues(Clicks=list()) # used for storing leaflet variables
tract_labels <- sprintf( # labels for mouseover tooltip
"<strong>%s</strong>, <strong>%s</strong>
<br/><b>Land Area:</b> %s",
philly$COUNTYFP,
philly$STATEFP,
philly$ALAND
) %>% lapply(htmltools::HTML)
output$mymap <- renderLeaflet({ # leaflet map
leaflet(data = philly) %>%
setView(-75.16, 39.9523, zoom = 10) %>%
addTiles(urlTemplate = "https://{s}.tile.openstreetmap.se/hydda/full/{z}/{x}/{y}.png",
attribution = NULL) %>%
addPolygons(data = philly,
layerId = philly@data$ALAND,
group = "regions",
fillColor = "#bdd7e7",
weight = 1,
opacity = 1.0,
fillOpacity = 0.5,
smoothFactor = 0.5,
label = tract_labels,
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "12px",
direction = "auto"),
highlightOptions = highlightOptions(color = "white",
weight = 2,
bringToFront = TRUE))
})
observeEvent({input$mymap_shape_click}, {
#create object for clicked polygon
click <- input$mymap_shape_click
RV$Clicks <- c(RV$Clicks,click$id)
#define leaflet proxy for second regional level map
proxy <- leafletProxy("mymap")
#subset regions shapefile by the clicked on polygons
selectedReg <- philly[philly@data$ALAND == click$id,]
#map clicked on polygons
proxy %>% addPolygons(data = selectedReg,
fillColor = "red",
fillOpacity = 1,
weight = 1,
color = "black",
stroke = T,
group = "selected",
layerId = selectedReg@data$ALAND)
# remove polygon group that are clicked twice
if(click$group == "selected"){
proxy %>%
clearGroup(group = "selected")
RV$Clicks <- 0 # resets values if polygons are clicked twice
}
mean.land <- mean(as.numeric(RV$Clicks)) # stores the values of polygons that are clicked
print(mean.land)
})
}
shinyApp(ui, server)
Essentially the map has two layers: the base tracts layer, and another tracts polygon that highlights what you click. You can click on each polygon to 'retrieve' a value (in this case it's land area, or variable ALAND) from each polygon and make calculations on it. Here I have selected three polygons, and I have used mean.land
variable to display the average land area of all three.
The reactiveValues RV
object is used to store a numeric value of the layerId
variable on any polygon that you click. This allows you to store and 'retrieve' it for other calculations you may want to make.
[1] 717210 # first click, first value
[1] 571940 # second click, averaged value
[1] 488678.3 # third click, averaged value
You can change extract the layerId
attribute by changing any references to variable ALAND in the code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With