maplibre-gl-interpolate-heatmap
v0.1.3
Published
Mapbox layer for average/interpolation heatmaps
Maintainers
Readme
MapLibre GL Interpolate Heatmap
A MapLibre GL JS custom layer for rendering interpolated heatmaps (extracting average values) with WebGL shaders. Works with MapLibre GL JS v5+ (WebGL2).
This library was greatly inspired by temperature-map-gl and depends on Earcut.
Density vs Interpolated Heatmaps
MapLibre provides a built-in heatmap layer that represents the density of points:

This library provides an interpolated heatmap that calculates colors based on the weighted average of surrounding point values:

Installation
# npm
npm install maplibre-gl-interpolate-heatmap maplibre-gl
# bun
bun add maplibre-gl-interpolate-heatmap maplibre-gl
# JSR
bunx jsr add @geoql/maplibre-gl-interpolate-heatmapUsage
import maplibregl from 'maplibre-gl';
import { MaplibreInterpolateHeatmapLayer } from 'maplibre-gl-interpolate-heatmap';
import 'maplibre-gl/dist/maplibre-gl.css';
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json',
center: [0, 20],
zoom: 2,
});
map.on('load', () => {
const layer = new MaplibreInterpolateHeatmapLayer({
id: 'temperature',
data: [
{ lat: 62.47, lon: 6.18, val: 16 },
{ lat: 48.09, lon: -1.37, val: 20 },
{ lat: 35.68, lon: 139.69, val: 28 },
],
opacity: 0.5,
minValue: 10,
maxValue: 35,
});
map.addLayer(layer);
});Options
| Option | Type | Default | Description |
| ------------------- | ------------------------ | ----------- | ---------------------------------------------------------------- |
| id | string | '' | Unique layer ID |
| data | Array<{lat, lon, val}> | [] | Data points (latitude must be within -85° to 85°) |
| opacity | number | 0.5 | Layer opacity (0-1) |
| minValue | number | Infinity | Value mapped to blue color |
| maxValue | number | -Infinity | Value mapped to red color |
| p | number | 3 | IDW power parameter (higher = more uniform colors around points) |
| framebufferFactor | number | 0.3 | Computation resolution (0-1, lower = faster but less accurate) |
| aoi | Array<{lat, lon}> | [] | Area of interest polygon (empty = entire map) |
| valueToColor | string | See below | GLSL function mapping value (0-1) to vec3 color |
| valueToColor4 | string | See below | GLSL function mapping value to vec4 with alpha |
Custom Color Functions
Default valueToColor (blue → green → red gradient):
vec3 valueToColor(float value) {
return vec3(
max((value - 0.5) * 2.0, 0.0),
1.0 - 2.0 * abs(value - 0.5),
max((0.5 - value) * 2.0, 0.0)
);
}Default valueToColor4:
vec4 valueToColor4(float value, float defaultOpacity) {
return vec4(valueToColor(value), defaultOpacity);
}How It Works
Colors are computed using Inverse Distance Weighting (IDW):
- Render N textures, each containing
wi * ui(red) andwi(green) per fragment - Blend textures with accumulator to sum all contributions
- Divide red by green channel to get interpolated value
u(x) - Map value to color using the GLSL color function
Where wi(x) = 1 / d(x, xi)^p is the weight based on distance.
Requirements
- Node.js >= 24.0.0
- MapLibre GL JS >= 3.0.0 (v5+ recommended for WebGL2)
Contributing
- Fork and create a feature branch from
main - Make changes following conventional commits
- Ensure commits are signed (why?)
- Submit a PR
bun install
bun run build
bun run lint
bun run formatLicense
MIT © Vinayak Kulkarni
