Heatmap Layer
Visualize point density as a continuous color gradient Each library has its own approach: here's how they compare.
Quick Recommendations
Leaflet — Ideal for quick heatmap overlays using the lightweight leaflet.heat plugin with simple [lat, lng, intensity] data arrays.
MapLibre GL JS — Best when the heatmap is part of a larger vector tile application and you need GPU-rendered density with zoom-dependent radius expressions.
OpenLayers — Ideal when heatmap data comes from existing vector features and you need built-in weight and gradient customization via ol.layer.Heatmap.
MapTiler SDK — For MapTiler SDK users, this means MapLibre's native heatmap layer plus automatic MapTiler basemap integration.
At a Glance
| Leaflet | MapLibre | OpenLayers | SDK | |
|---|---|---|---|---|
| Coordinates | [lat, lng] | [lng, lat] | fromLonLat([lng, lat]) | [lng, lat] |
| Rendering | DOM + Canvas (2D) | WebGL (GPU, 60fps) | Canvas + WebGL | WebGL (GPU, 60fps) |
| Bundle size | ~42 KB gzipped | ~250 KB gzipped | ~290 KB gzipped (tree-shakeable) | ~280 KB gzipped (includes MapLibre) |
| Learning curve | Easiest (simple API, great tutorials) | Moderate (source/layer model, expressions) | Steepest (projections, OGC standards, verbose API) | Easy (MapLibre API with convenience helpers) |
| 3D support | No native 3D (2D only) | Full: terrain, fill-extrusion, globe, sky | Limited: WebGL layers, no native globe | Full (same as MapLibre) |
| Code lines | 10 | 22 | 22 | 23 |
Code Snippets
Click a library to expand its code. Each snippet shows only the core logic: the scaffold handles HTML boilerplate.
Leaflet10 linesShow code
const map = L.map('map').setView([48.8566, 2.3522], 13);
L.tileLayer('https://api.maptiler.com/maps/streets-v4/256/{z}/{x}/{y}.png?key=YOUR_MAPTILER_KEY', {
tileSize: 256,
attribution: '© <a href="https://www.maptiler.com/">MapTiler</a> © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap contributors</a>'
}).addTo(map);
const points = [];
for (let i = 0; i < 200; i++) {
points.push([48.83 + Math.random() * 0.06, 2.28 + Math.random() * 0.15, Math.random()]);
}
L.heatLayer(points, { radius: 20, blur: 15, maxZoom: 17, max: 1.0, gradient: { 0.2: '#0000ff', 0.4: '#00ffff', 0.6: '#00ff00', 0.8: '#ffff00', 1.0: '#ff0000' } }).addTo(map);MapLibre GL JS22 linesShow code
const map = new maplibregl.Map({
container: 'map',
style: 'https://api.maptiler.com/maps/dataviz-dark/style.json?key=YOUR_MAPTILER_KEY',
center: [14.42, 50.08],
zoom: 10
});
const pts = [];
for (let i = 0; i < 500; i++) {
const a = Math.random() * Math.PI * 2, r = Math.random() * 0.1;
pts.push({ type: 'Feature', geometry: { type: 'Point', coordinates: [14.42 + Math.cos(a) * r, 50.08 + Math.sin(a) * r] },
properties: { weight: Math.random() } });
}
map.on('load', () => {
map.addSource('heat', { type: 'geojson', data: { type: 'FeatureCollection', features: pts } });
map.addLayer({ id: 'heatmap', type: 'heatmap', source: 'heat', paint: {
'heatmap-weight': ['get', 'weight'],
'heatmap-intensity': ['interpolate', ['linear'], ['zoom'], 8, 1, 13, 3],
'heatmap-color': ['interpolate', ['linear'], ['heatmap-density'], 0, 'rgba(33,102,172,0)', 0.2, '#4393c3', 0.4, '#d6604d', 0.6, '#f4a582', 0.8, '#fddbc7', 1, '#fff'],
'heatmap-radius': ['interpolate', ['linear'], ['zoom'], 8, 10, 13, 25],
'heatmap-opacity': 0.8
} });
});OpenLayers22 linesShow code
var features = [];
for (var i = 0; i < 500; i++) {
var feature = new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([2.3 + Math.random() * 0.15, 48.83 + Math.random() * 0.06])),
weight: Math.random()
});
features.push(feature);
}
var heatmap = new ol.layer.Heatmap({
source: new ol.source.Vector({ features: features }),
blur: 15,
radius: 10,
weight: function(feature) { return feature.get('weight'); }
});
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({ source: new ol.source.XYZ({ url: 'https://api.maptiler.com/maps/streets-v4/256/{z}/{x}/{y}.png?key=YOUR_MAPTILER_KEY', attributions: '© <a href="https://www.maptiler.com/copyright/">MapTiler</a>' }) }),
heatmap
],
view: new ol.View({ center: ol.proj.fromLonLat([2.37, 48.86]), zoom: 13 })
});MapTiler SDK23 linesShow code
maptilersdk.config.apiKey = 'YOUR_MAPTILER_KEY';
const map = new maptilersdk.Map({
container: 'map',
style: maptilersdk.MapStyle.STREETS,
center: [-98, 39],
zoom: 3
});
map.on('load', () => {
map.addSource('quakes', {
type: 'geojson',
data: 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson'
});
map.addLayer({
id: 'quake-heat', type: 'heatmap', source: 'quakes',
paint: {
'heatmap-weight': ['interpolate', ['linear'], ['get', 'mag'], 0, 0, 6, 1],
'heatmap-radius': ['interpolate', ['linear'], ['zoom'], 0, 2, 9, 20],
'heatmap-color': ['interpolate', ['linear'], ['heatmap-density'],
0, 'rgba(0,0,0,0)', 0.2, '#e8d5f5', 0.4, '#ce93d8',
0.6, '#9C27B0', 0.8, '#7b1fa2', 1, '#4a148c']
}
});
});Things to Know
Implementation-specific details that matter for heatmap layer.
Requires the external leaflet.heat plugin; input is a simple array of [lat, lng, intensity] values, not GeoJSON.
Native heatmap layer type with paint properties for radius, weight, color ramp, and intensity: no plugins needed.
ol.layer.Heatmap is built-in; weight is set per-feature via a property name, and gradient is an array of CSS colors.
Identical heatmap layer configuration to MapLibre using the same paint properties and GeoJSON source.
Which Library to Use?
Visualize point density as a heatmap on a Leaflet map using the leaflet.heat plugin.
Ideal for quick heatmap overlays using the lightweight leaflet.heat plugin with simple [lat, lng, intensity] data arrays.
Visualize point density using the native heatmap layer type: no plugins needed.
Best when the heatmap is part of a larger vector tile application and you need GPU-rendered density with zoom-dependent radius expressions.
Visualize point density using ol.layer.Heatmap with weighted features on a MapTiler basemap.
Ideal when heatmap data comes from existing vector features and you need built-in weight and gradient customization via ol.layer.Heatmap.
Visualize point density using a native heatmap layer with customizable radius and color ramp.
For MapTiler SDK users, this means MapLibre's native heatmap layer plus automatic MapTiler basemap integration.
Build Maps with AI
Generate code like these examples using mapping library skills in your IDE.