Responsive addWebGLHeatmap
with crosstalk and Leaflet in
Introduction
In this article, we will explore how to create a responsive heatmap using the addWebGLHeatmap
function from the Leaflet Extras library. We will also cover how to handle two main issues: redrawn heatmaps on zoom level changes and separation of heatmap points from markers.
Background
The original question comes from a user who is trying to create a leaflet map with a responsive heatmap using the addHeatmap
function from the Leaflet library. However, they are facing two main issues:
- Redrawn heatmaps on zoom level changes.
- Separation of heatmap points from markers.
To address these issues, we will use the addWebGLHeatmap
function and explore how to handle them using JavaScript code.
Step 1: Setting Up Leaflet Data
First, let’s create a sample data for our leaflet map:
# Create a new data frame with id, lat, lng, and group columns.
n <- 200
data <- data.frame(
id = seq(1, n * 2),
lat = rnorm(n, 0, 15),
long = rnorm(n, 0, 15),
group = c(rep("Heatmap", n), rep("Markers", n)),
mag = rep(as.integer(runif(n, 0, 20)), 2)
)
# Convert the data frame into a SharedData object.
sd <- SharedData$new(data)
Step 2: Creating Leaflet Map with addWebGLHeatmap
Next, let’s create our leaflet map using the bscols
function and adding the addWebGLHeatmap
layer:
# Create a new bscols object.
bscols <- bscols(widths = c(3, 9))
# Add filter slider for magnitude column.
filter_slider <- addFilterSlider(
sd,
"Magnitude",
sd$mag,
step = 0.1,
min = sd$mag[1],
max = sd$mag[n]
)
# Create leaflet map with setView, tiles, and markers.
leaflet(sd) %>%
addTiles() %>%
setView(lat = 0, lng = 0, zoom = 4) %>%
addMarkers(group = ~group) %>%
# Add webGL heatmap layer
leaflet::addWebGLHeatmap(
layerId = "heatmapwebgl",
size = 1000000,
units = "m",
alphaRange = c(0, 1)
) %>%
# Remove webGL heatmap layer when not visible.
leaflet.extras::removeWebGLHeatmap("heatmapwebgl") %>%
# Add layers control.
addLayersControl(
overlayGroups = c("Heatmap", "Markers"),
options = layersControlOptions(collapsed = FALSE)
) %>%
# Define function to render heatmap on map.
htmlwidgets::onRender(function(el, x) {
var myMap = this;
var coord_state;
// Hide heatmap markers
setTimeout(
function() {
myMap.eachLayer(function(layer) {
if (layer.options.group == "Heatmap") {
layer.setOpacity(0);
layer.getElement().style.pointerEvents = 'none';
}
})
},
100
)
// Function to get heatmap markers
function get_markers() {
coord_state = [];
myMap.eachLayer(function(layer) {
if (layer.options.group == "Heatmap") {
coord_state.push([layer.options.lat, layer.options.lng, 0.5]);
layer.getElement().style.pointerEvents = 'none';
}
});
return(coord_state);
}
// Function to redraw heatmap
function redraw_heatmap() {
heatmap.setData(get_markers());
}
var heatmap = L.webGLHeatmap({
size: 1000000,
units: "m",
alphaRange: c(0, 1)
});
heatmap.setData(get_markers());
myMap.addLayer(heatmap);
// Event listeners for layer add and remove
myMap.on("layerremove", redraw_heatmap);
myMap.on("layeradd", redraw_heatmap);
})
Step 3: Separating Heatmap Points from Markers
To separate heatmap points from markers, we need to adjust the opacity of each marker based on its group. We will use two separate addCircleMarkers
layers for heatmaps and markers.
# Create a new bscols object.
bscols <- bscols(widths = c(3, 9))
# Add filter slider for magnitude column.
filter_slider <- addFilterSlider(
sd,
"Magnitude",
sd$mag,
step = 0.1,
min = sd$mag[1],
max = sd$mag[n]
)
# Create leaflet map with setView, tiles, and markers.
leaflet(sd) %>%
addTiles() %>%
setView(lat = 0, lng = 0, zoom = 4) %>%
# Add heatmap layer
leaflet::addWebGLHeatmap(
layerId = "heatmapwebgl",
size = 1000000,
units = "m",
alphaRange = c(0, 1)
) %>%
# Remove webGL heatmap layer when not visible.
leaflet.extras::removeWebGLHeatmap("heatmapwebgl") %>%
# Add layers control for heatmaps and markers
addLayersControl(
overlayGroups = c("Heatmap", "Markers"),
options = layersControlOptions(collapsed = FALSE)
) %>%
# Define function to render heatmap on map.
htmlwidgets::onRender(function(el, x) {
var myMap = this;
var coord_state;
// Function to get heatmap markers
function get_markers() {
coord_state = [];
myMap.eachLayer(function(layer) {
if (layer.options.group == "Heatmap") {
coord_state.push([layer.options.lat, layer.options.lng, 0.5]);
}
});
return(coord_state);
}
// Function to redraw heatmap
function redraw_heatmap() {
heatmap.setData(get_markers());
}
var heatmap = L.webGLHeatmap({
size: 1000000,
units: "m",
alphaRange: c(0, 1)
});
heatmap.setData(get_markers());
myMap.addLayer(heatmap);
// Event listeners for layer add and remove
myMap.on("layerremove", redraw_heatmap);
myMap.on("layeradd", redraw_heatmap)
# Define function to render heatmap markers on map.
function get_markers() {
coord_state = [];
myMap.eachLayer(function(layer) {
if (layer.options.group == "Markers") {
coord_state.push([layer.options.lat, layer.options.lng]);
}
});
return(coord_state);
}
// Function to redraw heatmap markers
function redraw_heatmap() {
markers.setData(get_markers());
}
var markers = L.circleMarker()
.setLatLng([0, 0])
.addTo(myMap)
# Event listeners for layer add and remove
myMap.on("layerremove", redraw_heatmark);
myMap.on("layeradd", redraw_heatmark);
})
Conclusion
In this guide, we explored how to create a leaflet map with addWebGLHeatmap
and separate heatmap points from markers using JavaScript code. By following these steps, you can now visualize your data in a more interactive and efficient way.
Last modified on 2024-12-22