multiple - r leaflet layers
Cambio de estilos al seleccionar y anular la selección de múltiples polígonos con Leaflet/Shiny (1)
La respuesta está en layerIds. No entendía cómo se aplicaban a mis polígonos y cómo se quitaban las formas, entendiendo que esto es la clave. ¡Esta podría no ser la solución más elegante, pero hace el trabajo!
En el siguiente código, la representación del mapa inicial de Ruanda tiene un layerId
de rwa@data$NAME_1
, que son los nombres de la región. Puede ver esto en acción con la label
también configurada como rwa@data$NAME_1
. Entonces, en la imagen de abajo, el polígono más a la izquierda se etiqueta como Iburengerazuba, su atributo en la columna NAME_1
. Este layerId establece el click$id
para cualquier evento de clic que tenga en este renderizado inicial del mapa. Entonces, así como este polígono está etiquetado como Iburengerazuba, su click$id
también se configurará como Iburengerazuba. Como se indica en la documentación de Leaflet Shiny , si tiene más de un polígono, este debe ser un argumento vectorizado. Si solo necesita seleccionar y deseleccionar UN polígono (por lo tanto, solo una región a la vez, en este ejemplo), podría usar una cadena layerId
, como mencioné en mi pregunta (como layerId = "selected"
).
El siguiente paso es observeEvent
el observeEvent
para su forma de clic. Gracias a la ayuda del usuario @John Paul , descubrí cómo guardar todos los eventos de clic (haga clic en los ID específicamente en este caso) realizados en el mapa. Guardé esos en un vector reactivo, luego subconjunto mi shapefile por esos id. De clic. El código está bastante comentado, así que espero que cualquier otra persona que busque esta misma solución pueda descubrir exactamente qué está pasando.
El último bit de código (alojado en la sentencia condicional if...else
) es probablemente el más confuso. Miremos primero la parte else
del código. (Nota: su clic en el mapa inicial va a desencadenar este evento porque no hay forma de que las condiciones se hayan cumplido con el primer clic). Si se hace clic en un polígono blanco, se activa la llamada addPolygons()
se agrega el polígono al que se hace clic. el mapa con un estilo diferente (en este caso, es rojo). ¡Esto está trazando un polígono completamente diferente en la parte superior del objeto leafletProxy
!
La clave para eliminar los polígonos en rojo hace que estos polígonos layerId
un layerId
diferente del renderizado del mapa inicial. Tenga en cuenta que en la imagen de arriba, el polígono blanco que recibió la etiqueta Iburengerazuba ahora está etiquetado como 3. Esto se debe a que layerId
en la segunda llamada addPolygons
se establece como CCA_1
OF NAME_1
. Por lo tanto, el mapa blanco de la capa inferior tiene un NAME_1 layerID y, por lo tanto, NAME_1 hacen clic en los identificadores, mientras que cualquier polígono con un clic rojo trazado encima tiene un CCA_1 layerId y, por lo tanto, CCA_1 hace clic en los identificadores.
Las sentencias if
indican que si su click$id
ya existe en el polígono clickedPolys
, esta forma se elimina. Esto es algo confuso, así que de nuevo, podría ser útil ir a través de cada línea de código y jugar con ella para comprender realmente.
De nuevo, utilizando el ejemplo anterior, al hacer clic en el polígono layerId
más a la izquierda, se agrega la layerId
Id layerId
Iburengerazuba al vector clickedIds$ids
. Este evento de clic desencadena un segundo dibujo de mapa, trazando el polígono hecho clic encima de sí mismo en un estilo diferente y con un layerId
de 3 (de la columna CCA_1
). Queremos decir que si se hace clic dos veces en un polígono rojo ( if(click$id %in% clickedPolys@data$CCA_1)
), contará como deselección, y ese polígono debería eliminarse del mapa. Entonces, si haces clic en el polígono rojo más a la izquierda con un layerId
de 3, el vector clickedIds$ids
estará compuesto por Iburengerazuba
y 3
. Iburengerazuba en la columna clickedPolys
polígono clickedPolys
corresponde a 3 en la columna CCA_1
, lo que activa la sentencia if
. La llamada removeShape(layerId = click$id)
significa eliminar la forma que corresponde a ese clic $ id. Entonces, en este caso, el polígono clickedPolys
con CCA_1
layerId
de 3.
Tenga en cuenta que cada ID de clic, tanto NAME_1
como CCA_1
se registran en su vector clickedIds$ids
. Este vector está subdividiendo su shapefile de Ruanda para mapear todos los polígonos, de modo que al hacer clic en polígonos, el polígono clickedPolys
se actualiza dinámicamente (¡use print
llamadas de print
para verificar cada bit de código si esto no tiene sentido para usted!). La eliminación de cualquier forma de doble clic no es suficiente para trazar todo correctamente . Necesita eliminar los ID de capa deseleccionados, tanto NAME_1 como CCA_1, del vector clickedIds$ids
. CCA_1 layerId
cada CCA_1 layerId
deseleccionado con su correspondiente valor NAME_1
y NAME_1
ambos atributos del vector clickedIds$ids
para que se eliminen del polígono clickedPolys
.
Voila! ¡Ahora puede seleccionar y deseleccionar cualquier polígono que quiera!
library(raster)
library(shiny)
library(leaflet)
#load shapefile
rwa <- getData("GADM", country = "RWA", level = 1)
shinyApp(
ui = fluidPage(
leafletOutput("map")
),
server <- function(input, output, session){
#create empty vector to hold all click ids
clickedIds <- reactiveValues(ids = vector())
#initial map output
output$map <- renderLeaflet({
leaflet() %>%
addTiles() %>%
addPolygons(data = rwa,
fillColor = "white",
fillOpacity = 1,
color = "black",
stroke = T,
weight = 1,
layerId = rwa@data$NAME_1,
group = "regions",
label = rwa@data$NAME_1)
}) #END RENDER LEAFLET
observeEvent(input$map_shape_click, {
#create object for clicked polygon
click <- input$map_shape_click
#define leaflet proxy for second regional level map
proxy <- leafletProxy("map")
#append all click ids in empty vector
clickedIds$ids <- c(clickedIds$ids, click$id)
#shapefile with all clicked polygons - original shapefile subsetted by all admin names from the click list
clickedPolys <- rwa[rwa@data$NAME_1 %in% clickedIds$ids, ]
#if the current click ID [from CCA_1] exists in the clicked polygon (if it has been clicked twice)
if(click$id %in% clickedPolys@data$CCA_1){
#define vector that subsets NAME that matches CCA_1 click ID
nameMatch <- clickedPolys@data$NAME_1[clickedPolys@data$CCA_1 == click$id]
#remove the current click$id AND its name match from the clickedPolys shapefile
clickedIds$ids <- clickedIds$ids[!clickedIds$ids %in% click$id]
clickedIds$ids <- clickedIds$ids[!clickedIds$ids %in% nameMatch]
#remove that highlighted polygon from the map
proxy %>% removeShape(layerId = click$id)
} else {
#map highlighted polygons
proxy %>% addPolygons(data = clickedPolys,
fillColor = "red",
fillOpacity = 1,
weight = 1,
color = "black",
stroke = T,
label = clickedPolys@data$CCA_1,
layerId = clickedPolys@data$CCA_1)
} #END CONDITIONAL
}) #END OBSERVE EVENT
}) #END SHINYAPP
Tengo problemas para cambiar los estilos de polígono al seleccionar y anular la selección de polígonos en una aplicación Leaflet Shiny en la que estoy trabajando. En mi aplicación actual, cuando haces clic en un polígono, ese polígono se resalta con un color diferente. Idealmente, quiero que el usuario pueda seleccionar y resaltar múltiples polígonos. También quiero que el usuario pueda volver a hacer clic en un único polígono resaltado para anular su selección.
Lo mejor que he podido gestionar es seleccionar varios polígonos, darles el mismo ID de grupo "seleccionado" y luego anular la selección de ese grupo completo cuando se vuelve a hacer clic en un polígono. Aquí hay algunos ejemplos / código reproducible:
library(raster)
library(shiny)
library(leaflet)
#load shapefile
rwa <- getData("GADM", country = "RWA", level = 1)
shinyApp(
ui = fluidPage(
leafletOutput("map")
),
server <- function(input, output, session){
#initial map output
output$map <- renderLeaflet({
leaflet() %>%
addTiles() %>%
addPolygons(data = rwa,
fillColor = "white",
fillOpacity = 1,
color = "black",
stroke = T,
weight = 1,
layerId = rwa@data$OBJECTID,
group = "regions")
}) #END RENDER LEAFLET
observeEvent(input$map_shape_click, {
#create object for clicked polygon
click <- input$map_shape_click
#define leaflet proxy for second regional level map
proxy <- leafletProxy("map")
#subset regions shapefile by the clicked on polygons
selectedReg <-rwa[rwa@data$OBJECTID == click$id,]
#map clicked on polygons
proxy %>% addPolygons(data = selectedReg,
fillColor = "red",
fillOpacity = 1,
weight = 1,
color = "black",
stroke = T,
group = "selected",
# layerId = "selected")
layerId = selectedReg@data$OBJECTID)
#remove polygon group that are clicked twice
if(click$group == "selected"){
proxy %>%
clearGroup(group = "selected")
} #END CONDITIONAL
}) #END OBSERVE EVENT
}) #END SHINYAPP
En el ejemplo anterior, cada polígono cliqueado se vuelve rojo. Si se hace clic nuevamente en un polígono rojo previamente seleccionado, cada polígono rojo se borra del mapa, dejando las representaciones de polígono blanco inicial.
Puedo lograr el efecto de selección / anulación de selección deseado cuando estoy trabajando con un solo polígono a la vez utilizando la cadena layerId "selected" (comentada en el código anterior), pero al hacerlo elimino mi capacidad para seleccionar y resaltar varios polígonos. al mismo tiempo.
¡Estoy abierto a todas las sugerencias!