You should simply adapt the "Fancier Disable" example on your specific needs. In detail, you should create a listener associated to your map when the map zoom changes (zoomend
event) like in the attached example:
Javascript:
// listeners for disabling buttons
map.on('zoomend', function(e) {
var max = 15, // zoom limit to disable buttons
current = map.getZoom();
if (current < max) {
btn3.enable();
btn4.enable();
btn5.enable();
btn6.enable();
}
if (current >= max) {
btn3.disable();
btn4.disable();
btn5.disable();
btn6.disable();
}
});
CSS:
.leaflet-bar.disabled,
.leaflet-bar button.disabled {
opacity: 0;
border: none;
}
Note: the CSS above is necessary in order to hide the buttons, otherwise we would get the same effect of the "Simple disable" example.
The id
column of the data.frame
must be of class character
or factor
. I modified the id
vector when creating the data.frame
. Try the working code below. You will be able to add and remove markers when check/uncheck the checkboxes.
# Load libraries
library("leaflet")
ui <- shinyUI(fluidPage(sidebarLayout(
sidebarPanel(
checkboxInput("delete1", "Delete ID=1 and ID=2", value = FALSE),
checkboxInput("delete3", "Delete ID=3", value = FALSE)
),
mainPanel(leafletOutput("map"))
)))
# ID must be a character
df <- data.frame(
id = as.character(c(1, 2, 3)),
lng = rnorm(3, -106.1039361, 0.5),
lat = rnorm(3, 50.543981, 0.5)
)
server <- shinyServer(function(input, output, session) {
output$map <- renderLeaflet(
leaflet() %>%
addTiles() %>% addCircleMarkers(
layerId = df$id,
df$lng,
df$lat,
group = 'marker',
radius = 2,
fill = TRUE,
color = 'red'
)
)
observeEvent(input$delete1, {
proxy <- leafletProxy('map')
if (input$delete1) {
proxy %>% removeMarker(layerId = df$id[1:2])
}
if (!input$delete1) {
proxy %>% addCircleMarkers(
layerId = df$id[1:2],
df$lng[1:2],
df$lat[1:2],
group = 'marker',
radius = 2,
fill = TRUE,
color = 'red'
)
}
})
observeEvent(input$delete3, {
proxy <- leafletProxy('map')
if (input$delete3) {
proxy %>% removeMarker(layerId = df$id[3])
}
if (!input$delete3) {
proxy %>% addCircleMarkers(
layerId = df$id[3],
df$lng[3],
df$lat[3],
group = 'marker',
radius = 2,
fill = TRUE,
color = 'red'
)
}
})
})
shinyApp(ui, server)
Edit1:
Based on Cluster markers
# Load libraries
library("leaflet")
ui <- shinyUI(fluidPage(sidebarLayout(
sidebarPanel(
hr(),
h4("Remove points"),
checkboxGroupInput(
inputId = "removeFromMap",
label = "",
choices = c(1:6)
),
p("Cluster1 = 1,2,3"),
p("Cluster2 = 4,5,6"),
hr(),
p("Checked = removed"),
p("Unchecked = present")
),
mainPanel(leafletOutput("map"))
)))
# ID must be a character
df <- data.frame(
id = as.character(1:6),
lng = rnorm(6, -106.1039361, 0.5),
lat = rnorm(6, 50.543981, 0.5)
)
server <- shinyServer(function(input, output, session) {
output$map <- renderLeaflet(
leaflet() %>%
setView(-106.1039361, 50.543981, zoom = 5) %>%
addTiles() %>%
addCircleMarkers(
layerId = df$id[1:3],
df$lng[1:3],
df$lat[1:3],
group = 'marker',
radius = 3,
fill = TRUE,
color = '#EF2929',
clusterId = "Cluster1",
clusterOptions = markerClusterOptions()
) %>%
addCircleMarkers(
layerId = df$id[4:6],
df$lng[4:6],
df$lat[4:6],
group = 'marker',
radius = 3,
fill = TRUE,
color = '#729FCF',
clusterId = "Cluster2",
clusterOptions = markerClusterOptions()
)
)
# Global ID vector
ids <- df$id
# Remove points
observeEvent(input$removeFromMap, {
checkedPoints <- input$removeFromMap
checkedPoints <- checkedPoints[which(checkedPoints %in% ids)]
proxy <- leafletProxy('map')
if (length(checkedPoints) != 0) {
if (any(checkedPoints %in% as.character(1:3))) {
pointsC1 <- checkedPoints[which(checkedPoints %in% ids)]
proxy %>% removeMarkerFromCluster(layerId = pointsC1, clusterId = "Cluster1")
ids <<- ids[-which(ids == pointsC1)]
}
if (any(checkedPoints %in% as.character(4:6))) {
pointsC2 <- checkedPoints[which(checkedPoints %in% ids)]
proxy %>% removeMarkerFromCluster(layerId = pointsC2, clusterId = "Cluster2")
ids <<- ids[-which(ids == pointsC2)]
}
}
})
})
shinyApp(ui, server)
Best Answer
I think you're using the wrong tool (GeoJSON) for the job (showing markers depending on a condition). I'd approach the problem with individual markers, something like:
If you want to dinamically show/hide categories of markers, create a
L.LayerGroup
per category, add the markers to a group instead of to the map, and use aL.Control.Layers
to let the user control the visibility.