I'm developing an R Shiny app and want to have an interactive map, where the user clicks on a region (or subregion), and the map automatically zooms and scales the view to fit the selected region. This is essentially the same question as posted here, except in that solution, the solution involved manually-provided 'Zoom' levels for each state; I'm looking for a way to automate this (I have hundreds of subregions that vary dramatically in size).
So far, I have something similar to what that previous post has done, here I've manually set a zoom level to 7 based on where the mouse clicks. The problems with this approach are: 1) the zoom is the same for all clicks, 2) the view changes based on what part of the map is selected (ideally, I want the same view of each region/polygon regardless of where inside that polygon is clicked), and 3) once I click, the zoom seems fixed - I can't pan in or out of the map.
Current code:
library(shiny)
library(bcmaps)
library(sf)
library(leaflet)
library(dplyr)
# setup one map for use in the app - taken from 'bcmaps' package
ha <- health_ha() %>%
rename_with(tolower, everything()) %>%
dplyr::select(ha_code = hlth_authority_code,
ha_name = hlth_authority_name,
geometry) %>%
st_transform(crs = 4326) %>%
mutate(color = c("#3891A7",
"#C3860D",
"#C42E2E",
"#67A63C",
"#914FAB"))
# Shiny app:
ui <- page_fluid(
layout_columns(leafletOutput("interactive_map"),
plotOutput("map")
))
server <- function(input, output, session) {
output$interactive_map <- renderLeaflet({
leaflet() %>%
addProviderTiles("Esri.WorldImagery", group = "Satellite") %>%
addPolygons(data = ha,
group = "Health Authority",
stroke = TRUE,
weight = 1,
color = ~color,
opacity = 0.5,
fillColor = ~color,
fillOpacity = 0.3,
# add highlight on hover:
highlight = highlightOptions(weight = 4, color = "darkblue",
fillOpacity = 0.7,
bringToFront = TRUE))
})
# add in zoom-on-click functionality:
observe(
{click <- input$interactive_map_shape_click
# is the _bounds function useful?
# the 'sf' package also has a st_bbox() function to return bounds of a polygon
# lims <- input$interactive_map_bounds
if(is.null(click))
return()
else
leafletProxy("interactive_map") %>%
setView(lng = click$lng, lat = click$lat, zoom = 7)
# is 'fitBounds' better to use? not sure if this is the right syntax:
# fitBounds(lng1 = lims[[1]], lat1 = lims[[2]],
# lng2 = lims[[3]], lat2 = lims[[4]])
}
)
}
# Run the application
shinyApp(ui = ui, server = server)```