/**
* BeNomad BeMap JavaScript API - MapLibre v5 - Heatmap
*
* Usage:
* var heatmap = new bemap.HeatmapLayer({
* name: 'earthquakes',
* points: [
* { lon: 2.35, lat: 48.85, weight: 5 },
* { lon: 7.26, lat: 43.71, weight: 3 }
* ],
* radius: 25,
* intensity: 1.5,
* colors: ['rgba(0,0,255,0)', 'royalblue', 'cyan', 'lime', 'yellow', 'red']
* });
* map.addHeatmap(heatmap);
*/
bemap.MapLibreMap.prototype.addHeatmap = function(layer, options) {
if (!layer || !bemap.inheritsof(layer, bemap.HeatmapLayer)) return this;
var _this = this;
this._addOwnToProperties(layer);
var sourceId = layer._bemapId + '-heatmap-src';
var layerId = layer._bemapId + '-heatmap';
layer._maplibreSourceId = sourceId;
layer._maplibreLayerId = layerId;
// Build GeoJSON FeatureCollection from points
var features = [];
for (var i = 0; i < layer.points.length; i++) {
var pt = layer.points[i];
features.push({
type: 'Feature',
geometry: { type: 'Point', coordinates: [pt.lon, pt.lat] },
properties: { weight: pt.weight || pt[layer.weightProperty] || 1 }
});
}
var geojsonData = { type: 'FeatureCollection', features: features };
// Build color ramp
var colorRamp = ['interpolate', ['linear'], ['heatmap-density']];
var colors = layer.colors;
for (var c = 0; c < colors.length; c++) {
colorRamp.push(c / (colors.length - 1));
colorRamp.push(colors[c]);
}
var addToMap = function() {
if (!_this.native.getSource(sourceId)) {
_this.native.addSource(sourceId, { type: 'geojson', data: geojsonData });
_this.native.addLayer({
id: layerId,
type: 'heatmap',
source: sourceId,
paint: {
'heatmap-weight': ['interpolate', ['linear'], ['get', 'weight'], 0, 0, 10, 1],
'heatmap-intensity': ['interpolate', ['linear'], ['zoom'], 0, layer.intensity, 20, layer.intensity * 3],
'heatmap-color': colorRamp,
'heatmap-radius': ['interpolate', ['linear'], ['zoom'], 0, 2, 20, layer.radius],
'heatmap-opacity': layer.opacity
}
});
}
};
if (this.native.isStyleLoaded()) { addToMap(); } else { this.native.on('load', addToMap); }
layer.native = { sourceId: sourceId, layerId: layerId };
if (layer.map === null) layer.map = this;
var _self = this;
if (typeof this._registerEffect === 'function') {
this._registerEffect('heatmap:' + layer._bemapId, function () { _self.removeHeatmap(layer); });
}
return this;
};
bemap.MapLibreMap.prototype.removeHeatmap = function(layer) {
if (layer && layer.native) {
try {
if (this.native.getLayer(layer._maplibreLayerId)) this.native.removeLayer(layer._maplibreLayerId);
if (this.native.getSource(layer._maplibreSourceId)) this.native.removeSource(layer._maplibreSourceId);
} catch(e) {}
if (typeof this._unregisterEffect === 'function' && layer._bemapId) {
this._unregisterEffect('heatmap:' + layer._bemapId);
}
if (layer._bemapId) delete this._featureRegistry[layer._bemapId];
layer.map = null;
}
return this;
};
bemap.MapLibreMap.prototype.updateHeatmap = function(layer, data) {
if (layer && layer._maplibreSourceId) {
var features = [];
for (var i = 0; i < data.length; i++) {
var pt = data[i];
features.push({
type: 'Feature',
geometry: { type: 'Point', coordinates: [pt.lon, pt.lat] },
properties: { weight: pt.weight || 1 }
});
}
var src = this.native.getSource(layer._maplibreSourceId);
if (src) src.setData({ type: 'FeatureCollection', features: features });
layer.points = data;
}
return this;
};