Heatmap Layer
Continuous density visualization using Kernel Density Estimation (KDE). Creates smooth color gradients representing data concentration, ideal for identifying "hot zones" on the ice.
Basic Heatmap
The simplest usage creates a smooth density visualization of shot locations.
import { Rink, NHLDataManager } from "d3-hockey";
// 1. Load Data
const manager = await NHLDataManager.fromGameId("2022020195");
const shots = manager.getAllEvents({ shotsOnly: true });
// 2. Render Rink with Heatmap Layer
new Rink("#container").render().addHeatmap(shots, {
bandwidth: 5, // Smoothing radius in feet
maxOpacity: 0.8, // Peak density opacity
});Bandwidth Comparison
The bandwidth parameter controls how "spread out" each point's influence is. Lower values create tighter, more detailed heatmaps, while higher values create smoother, more generalized views.
new Rink("#container").render().addHeatmap(shots, {
bandwidth: 3, // Tight, detailed view
maxOpacity: 0.85,
threshold: 0.08,
});new Rink("#container").render().addHeatmap(shots, {
bandwidth: 10, // Smooth, generalized view
maxOpacity: 0.75,
});Custom Color Scales
Use D3 color scales to customize the heatmap appearance.
import * as d3 from "d3";
new Rink("#container").render().addHeatmap(shots, {
bandwidth: 5,
colorScale: d3.scaleSequential(d3.interpolateViridis),
maxOpacity: 0.9,
});new Rink("#container").render().addHeatmap(shots, {
bandwidth: 5,
colorScale: d3.scaleSequential(d3.interpolateInferno),
maxOpacity: 0.85,
});Threshold Filtering
Use threshold to filter out low-density areas and focus on hot zones.
new Rink("#container").render().addHeatmap(shots, {
bandwidth: 4,
threshold: 0.2, // Only show top 80% density
maxOpacity: 0.9,
});Heatmap vs Hexbin Comparison
Compare the continuous heatmap with discrete hexagonal binning.
// Heatmap - smooth, continuous density
new Rink("#heatmap").render().addHeatmap(shots, {
bandwidth: 5,
maxOpacity: 0.8,
});
// Hexbin - discrete hexagonal bins
new Rink("#hexbin").render().addHexbin(shots, {
radius: 4,
opacity: 0.8,
});Combined with Event Layer
Layer a heatmap beneath individual shot markers for context.
new Rink("#container")
.render()
.addHeatmap(shots, {
id: "density",
bandwidth: 6,
maxOpacity: 0.6,
zIndex: 5,
})
.addEvents(goals, {
id: "goals",
color: "#FFD700",
radius: 6,
symbol: "star",
zIndex: 10,
});When to Use Heatmap vs Hexbin
| Feature | Heatmap | Hexbin |
|---|---|---|
| Visual style | Smooth, continuous gradient | Discrete hexagonal cells |
| Best for | Identifying general "hot zones" | Precise counts & aggregations |
| Performance | Canvas-based, handles large data | SVG-based, interactive bins |
| Tooltips | Position-based density | Per-bin aggregated values |
| Aggregation | Density only | Count, mean, sum, etc. |
API Reference
See the full HeatmapLayer API documentation for all configuration options.