leaflet-heatmap-layer 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +87 -0
- package/dist/HeatLayer.d.ts +55 -0
- package/dist/HeatRenderer.d.ts +34 -0
- package/dist/index.d.ts +7 -0
- package/dist/leaflet-heatmap-layer.cjs.js +422 -0
- package/dist/leaflet-heatmap-layer.cjs.js.map +7 -0
- package/dist/leaflet-heatmap-layer.esm.js +391 -0
- package/dist/leaflet-heatmap-layer.esm.js.map +7 -0
- package/dist/leaflet-heatmap-layer.umd.js +434 -0
- package/dist/leaflet-heatmap-layer.umd.js.map +7 -0
- package/package.json +58 -0
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var LeafletHeatmapLayer = (() => {
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
10
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
|
+
};
|
|
12
|
+
var __export = (target, all) => {
|
|
13
|
+
for (var name in all)
|
|
14
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
15
|
+
};
|
|
16
|
+
var __copyProps = (to, from, except, desc) => {
|
|
17
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
18
|
+
for (let key of __getOwnPropNames(from))
|
|
19
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
20
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
21
|
+
}
|
|
22
|
+
return to;
|
|
23
|
+
};
|
|
24
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
25
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
26
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
27
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
28
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
29
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
30
|
+
mod
|
|
31
|
+
));
|
|
32
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
33
|
+
|
|
34
|
+
// leaflet-global:leaflet
|
|
35
|
+
var require_leaflet = __commonJS({
|
|
36
|
+
"leaflet-global:leaflet"(exports, module) {
|
|
37
|
+
module.exports = L;
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// src/index.ts
|
|
42
|
+
var index_exports = {};
|
|
43
|
+
__export(index_exports, {
|
|
44
|
+
HeatLayer: () => HeatLayer,
|
|
45
|
+
HeatRenderer: () => HeatRenderer,
|
|
46
|
+
heatLayer: () => heatLayer
|
|
47
|
+
});
|
|
48
|
+
var import_leaflet = __toESM(require_leaflet());
|
|
49
|
+
|
|
50
|
+
// src/HeatLayer.ts
|
|
51
|
+
var L2 = __toESM(require_leaflet());
|
|
52
|
+
|
|
53
|
+
// src/HeatRenderer.ts
|
|
54
|
+
var DEFAULT_GRADIENT = {
|
|
55
|
+
0.4: "blue",
|
|
56
|
+
0.6: "cyan",
|
|
57
|
+
0.7: "lime",
|
|
58
|
+
0.8: "yellow",
|
|
59
|
+
1: "red"
|
|
60
|
+
};
|
|
61
|
+
var HeatRenderer = class {
|
|
62
|
+
constructor(canvas, options) {
|
|
63
|
+
this._circle = null;
|
|
64
|
+
this._palette = null;
|
|
65
|
+
this._canvas = canvas;
|
|
66
|
+
const ctx = canvas.getContext("2d");
|
|
67
|
+
if (!ctx) throw new Error("Could not get 2d context from canvas");
|
|
68
|
+
this._ctx = ctx;
|
|
69
|
+
this._radius = options?.radius ?? 25;
|
|
70
|
+
this._blur = options?.blur ?? 15;
|
|
71
|
+
this._minOpacity = options?.minOpacity ?? 0.05;
|
|
72
|
+
this._gradient = options?.gradient ?? DEFAULT_GRADIENT;
|
|
73
|
+
}
|
|
74
|
+
setOptions(options) {
|
|
75
|
+
if (options.radius !== void 0 || options.blur !== void 0) {
|
|
76
|
+
this._radius = options.radius ?? this._radius;
|
|
77
|
+
this._blur = options.blur ?? this._blur;
|
|
78
|
+
this._circle = null;
|
|
79
|
+
}
|
|
80
|
+
if (options.gradient !== void 0) {
|
|
81
|
+
this._gradient = options.gradient;
|
|
82
|
+
this._palette = null;
|
|
83
|
+
}
|
|
84
|
+
if (options.minOpacity !== void 0) {
|
|
85
|
+
this._minOpacity = options.minOpacity;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
get radius() {
|
|
89
|
+
return this._radius;
|
|
90
|
+
}
|
|
91
|
+
get blur() {
|
|
92
|
+
return this._blur;
|
|
93
|
+
}
|
|
94
|
+
resize(width, height) {
|
|
95
|
+
this._canvas.width = width;
|
|
96
|
+
this._canvas.height = height;
|
|
97
|
+
}
|
|
98
|
+
clear() {
|
|
99
|
+
this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
|
|
100
|
+
}
|
|
101
|
+
/** Draw the heatmap. Intensity values should be pre-normalized to 0–1. */
|
|
102
|
+
draw(points) {
|
|
103
|
+
if (points.length === 0) {
|
|
104
|
+
this.clear();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const circle = this._getCircle();
|
|
108
|
+
const fullRadius = this._radius + this._blur;
|
|
109
|
+
this.clear();
|
|
110
|
+
for (const [x, y, intensity] of points) {
|
|
111
|
+
this._ctx.globalAlpha = Math.max(intensity, this._minOpacity);
|
|
112
|
+
this._ctx.drawImage(circle, x - fullRadius, y - fullRadius);
|
|
113
|
+
}
|
|
114
|
+
this._colorize();
|
|
115
|
+
}
|
|
116
|
+
_getCircle() {
|
|
117
|
+
if (this._circle) return this._circle;
|
|
118
|
+
const r = this._radius;
|
|
119
|
+
const blur = this._blur;
|
|
120
|
+
const fullRadius = r + blur;
|
|
121
|
+
const diameter = fullRadius * 2;
|
|
122
|
+
const circle = document.createElement("canvas");
|
|
123
|
+
circle.width = diameter;
|
|
124
|
+
circle.height = diameter;
|
|
125
|
+
const ctx = circle.getContext("2d");
|
|
126
|
+
ctx.shadowOffsetX = diameter;
|
|
127
|
+
ctx.shadowOffsetY = diameter;
|
|
128
|
+
ctx.shadowBlur = blur;
|
|
129
|
+
ctx.shadowColor = "black";
|
|
130
|
+
ctx.beginPath();
|
|
131
|
+
ctx.arc(fullRadius - diameter, fullRadius - diameter, r, 0, Math.PI * 2, true);
|
|
132
|
+
ctx.closePath();
|
|
133
|
+
ctx.fill();
|
|
134
|
+
this._circle = circle;
|
|
135
|
+
return circle;
|
|
136
|
+
}
|
|
137
|
+
_getPalette() {
|
|
138
|
+
if (this._palette) return this._palette;
|
|
139
|
+
const paletteCanvas = document.createElement("canvas");
|
|
140
|
+
paletteCanvas.width = 256;
|
|
141
|
+
paletteCanvas.height = 1;
|
|
142
|
+
const ctx = paletteCanvas.getContext("2d");
|
|
143
|
+
const grad = ctx.createLinearGradient(0, 0, 256, 0);
|
|
144
|
+
for (const [stop, color] of Object.entries(this._gradient)) {
|
|
145
|
+
grad.addColorStop(Number(stop), color);
|
|
146
|
+
}
|
|
147
|
+
ctx.fillStyle = grad;
|
|
148
|
+
ctx.fillRect(0, 0, 256, 1);
|
|
149
|
+
this._palette = ctx.getImageData(0, 0, 256, 1).data;
|
|
150
|
+
return this._palette;
|
|
151
|
+
}
|
|
152
|
+
/** Map alpha channel (greyscale intensity) to gradient colors. */
|
|
153
|
+
_colorize() {
|
|
154
|
+
const w = this._canvas.width;
|
|
155
|
+
const h = this._canvas.height;
|
|
156
|
+
if (w === 0 || h === 0) return;
|
|
157
|
+
const imageData = this._ctx.getImageData(0, 0, w, h);
|
|
158
|
+
const pixels = imageData.data;
|
|
159
|
+
const palette = this._getPalette();
|
|
160
|
+
for (let i = 0, len = pixels.length; i < len; i += 4) {
|
|
161
|
+
const alpha = pixels[i + 3];
|
|
162
|
+
if (alpha === 0) continue;
|
|
163
|
+
const paletteOffset = alpha * 4;
|
|
164
|
+
pixels[i] = palette[paletteOffset];
|
|
165
|
+
pixels[i + 1] = palette[paletteOffset + 1];
|
|
166
|
+
pixels[i + 2] = palette[paletteOffset + 2];
|
|
167
|
+
}
|
|
168
|
+
this._ctx.putImageData(imageData, 0, 0);
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
// src/HeatLayer.ts
|
|
173
|
+
var HeatLayer = class extends L2.Layer {
|
|
174
|
+
constructor(latlngs, options) {
|
|
175
|
+
super(options);
|
|
176
|
+
this._canvas = null;
|
|
177
|
+
this._renderer = null;
|
|
178
|
+
this._frame = null;
|
|
179
|
+
this._snapshotCanvas = null;
|
|
180
|
+
this._zooming = false;
|
|
181
|
+
this._crossfadeTimer = null;
|
|
182
|
+
this._latlngs = latlngs;
|
|
183
|
+
this._options = {
|
|
184
|
+
radius: 25,
|
|
185
|
+
blur: 15,
|
|
186
|
+
minOpacity: 0.05,
|
|
187
|
+
...options
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
onAdd(map) {
|
|
191
|
+
this._map = map;
|
|
192
|
+
if (!this._canvas) {
|
|
193
|
+
this._createCanvas();
|
|
194
|
+
}
|
|
195
|
+
const pane = this.getPane();
|
|
196
|
+
if (pane && this._canvas) {
|
|
197
|
+
pane.appendChild(this._canvas);
|
|
198
|
+
}
|
|
199
|
+
map.on("moveend", this._onMoveEnd, this);
|
|
200
|
+
map.on("zoomanim", this._onZoomAnim, this);
|
|
201
|
+
this._onMoveEnd();
|
|
202
|
+
return this;
|
|
203
|
+
}
|
|
204
|
+
onRemove(map) {
|
|
205
|
+
if (this._frame !== null) {
|
|
206
|
+
cancelAnimationFrame(this._frame);
|
|
207
|
+
this._frame = null;
|
|
208
|
+
}
|
|
209
|
+
this._clearCrossfade();
|
|
210
|
+
if (this._snapshotCanvas && this._snapshotCanvas.parentNode) {
|
|
211
|
+
this._snapshotCanvas.parentNode.removeChild(this._snapshotCanvas);
|
|
212
|
+
}
|
|
213
|
+
this._snapshotCanvas = null;
|
|
214
|
+
const pane = this.getPane();
|
|
215
|
+
if (pane && this._canvas) {
|
|
216
|
+
pane.removeChild(this._canvas);
|
|
217
|
+
}
|
|
218
|
+
map.off("moveend", this._onMoveEnd, this);
|
|
219
|
+
map.off("zoomanim", this._onZoomAnim, this);
|
|
220
|
+
return this;
|
|
221
|
+
}
|
|
222
|
+
/** Replace all data points and redraw. */
|
|
223
|
+
setLatLngs(latlngs) {
|
|
224
|
+
this._latlngs = latlngs;
|
|
225
|
+
return this.redraw();
|
|
226
|
+
}
|
|
227
|
+
/** Add a single data point and redraw. */
|
|
228
|
+
addLatLng(latlng) {
|
|
229
|
+
this._latlngs.push(latlng);
|
|
230
|
+
return this.redraw();
|
|
231
|
+
}
|
|
232
|
+
/** Update options and redraw. */
|
|
233
|
+
setOptions(options) {
|
|
234
|
+
Object.assign(this._options, options);
|
|
235
|
+
if (this._renderer) {
|
|
236
|
+
this._renderer.setOptions({
|
|
237
|
+
radius: this._options.radius,
|
|
238
|
+
blur: this._options.blur,
|
|
239
|
+
minOpacity: this._options.minOpacity,
|
|
240
|
+
gradient: this._options.gradient
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
return this.redraw();
|
|
244
|
+
}
|
|
245
|
+
/** Return a LatLngBounds covering all data points, or an invalid bounds if empty. */
|
|
246
|
+
getBounds() {
|
|
247
|
+
if (this._latlngs.length === 0) return L2.latLngBounds([]);
|
|
248
|
+
return L2.latLngBounds(this._latlngs.map((p) => this._toLatLng(p)));
|
|
249
|
+
}
|
|
250
|
+
/** Schedule a redraw on the next animation frame. */
|
|
251
|
+
redraw() {
|
|
252
|
+
if (this._map && this._frame === null) {
|
|
253
|
+
this._frame = requestAnimationFrame(() => {
|
|
254
|
+
this._frame = null;
|
|
255
|
+
this._redraw();
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
return this;
|
|
259
|
+
}
|
|
260
|
+
_createCanvas() {
|
|
261
|
+
this._canvas = document.createElement("canvas");
|
|
262
|
+
this._canvas.style.position = "absolute";
|
|
263
|
+
this._canvas.style.pointerEvents = "none";
|
|
264
|
+
this._canvas.style.willChange = "transform";
|
|
265
|
+
this._canvas.style.transformOrigin = "0 0";
|
|
266
|
+
const animated = this._map.options.zoomAnimation && L2.Browser.any3d;
|
|
267
|
+
L2.DomUtil.addClass(
|
|
268
|
+
this._canvas,
|
|
269
|
+
"leaflet-zoom-" + (animated ? "animated" : "hide")
|
|
270
|
+
);
|
|
271
|
+
this._renderer = new HeatRenderer(this._canvas, {
|
|
272
|
+
radius: this._options.radius,
|
|
273
|
+
blur: this._options.blur,
|
|
274
|
+
minOpacity: this._options.minOpacity,
|
|
275
|
+
gradient: this._options.gradient
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
_onMoveEnd() {
|
|
279
|
+
if (!this._map || !this._canvas) return;
|
|
280
|
+
const wasZooming = this._zooming;
|
|
281
|
+
this._zooming = false;
|
|
282
|
+
const duration = this._options.zoomCrossfadeDuration ?? 250;
|
|
283
|
+
if (wasZooming && duration > 0) {
|
|
284
|
+
this._takeSnapshot();
|
|
285
|
+
}
|
|
286
|
+
const size = this._map.getSize();
|
|
287
|
+
const topLeft = this._map.containerPointToLayerPoint([0, 0]);
|
|
288
|
+
L2.DomUtil.setPosition(this._canvas, topLeft);
|
|
289
|
+
this._renderer.resize(size.x, size.y);
|
|
290
|
+
this._redraw();
|
|
291
|
+
if (wasZooming && duration > 0) {
|
|
292
|
+
this._startCrossfade(duration);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
/** Apply CSS transform during zoom animation (same approach as Leaflet's ImageOverlay). */
|
|
296
|
+
_onZoomAnim(e) {
|
|
297
|
+
if (!this._map || !this._canvas) return;
|
|
298
|
+
this._zooming = true;
|
|
299
|
+
const map = this._map;
|
|
300
|
+
const scale = map.getZoomScale(e.zoom);
|
|
301
|
+
const canvasPos = L2.DomUtil.getPosition(this._canvas);
|
|
302
|
+
const topLeftLatLng = map.layerPointToLatLng(canvasPos);
|
|
303
|
+
const layerTopLeft = map.containerPointToLayerPoint([0, 0]);
|
|
304
|
+
const newPos = map.project(topLeftLatLng, e.zoom).subtract(map.project(e.center, e.zoom)).add(map.getSize().divideBy(2)).add(layerTopLeft).round();
|
|
305
|
+
L2.DomUtil.setTransform(this._canvas, newPos, scale);
|
|
306
|
+
}
|
|
307
|
+
_takeSnapshot() {
|
|
308
|
+
if (!this._canvas) return;
|
|
309
|
+
this._clearCrossfade();
|
|
310
|
+
const canvas = this._canvas;
|
|
311
|
+
if (!this._snapshotCanvas) {
|
|
312
|
+
this._snapshotCanvas = document.createElement("canvas");
|
|
313
|
+
this._snapshotCanvas.style.position = "absolute";
|
|
314
|
+
this._snapshotCanvas.style.pointerEvents = "none";
|
|
315
|
+
}
|
|
316
|
+
const snap = this._snapshotCanvas;
|
|
317
|
+
snap.width = canvas.width;
|
|
318
|
+
snap.height = canvas.height;
|
|
319
|
+
snap.getContext("2d").drawImage(canvas, 0, 0);
|
|
320
|
+
snap.style.transform = canvas.style.transform;
|
|
321
|
+
snap.style.transformOrigin = canvas.style.transformOrigin;
|
|
322
|
+
snap.style.opacity = "1";
|
|
323
|
+
snap.style.transition = "";
|
|
324
|
+
if (canvas.parentNode) {
|
|
325
|
+
canvas.after(snap);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
_startCrossfade(duration) {
|
|
329
|
+
const snap = this._snapshotCanvas;
|
|
330
|
+
if (!snap) return;
|
|
331
|
+
snap.style.transition = `opacity ${duration}ms ease-out`;
|
|
332
|
+
snap.offsetHeight;
|
|
333
|
+
snap.style.opacity = "0";
|
|
334
|
+
this._crossfadeTimer = window.setTimeout(() => {
|
|
335
|
+
this._crossfadeTimer = null;
|
|
336
|
+
if (snap) {
|
|
337
|
+
snap.style.transition = "";
|
|
338
|
+
}
|
|
339
|
+
}, duration);
|
|
340
|
+
}
|
|
341
|
+
_clearCrossfade() {
|
|
342
|
+
if (this._crossfadeTimer !== null) {
|
|
343
|
+
clearTimeout(this._crossfadeTimer);
|
|
344
|
+
this._crossfadeTimer = null;
|
|
345
|
+
}
|
|
346
|
+
if (this._snapshotCanvas) {
|
|
347
|
+
this._snapshotCanvas.style.transition = "";
|
|
348
|
+
this._snapshotCanvas.style.opacity = "0";
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
_redraw() {
|
|
352
|
+
if (!this._map || !this._renderer || !this._canvas) return;
|
|
353
|
+
const map = this._map;
|
|
354
|
+
const size = map.getSize();
|
|
355
|
+
if (size.x === 0 || size.y === 0) return;
|
|
356
|
+
const renderer = this._renderer;
|
|
357
|
+
const r = renderer.radius + renderer.blur;
|
|
358
|
+
const cellSize = Math.max(1, Math.floor(renderer.radius / 2));
|
|
359
|
+
const maxZoom = this._options.maxZoom ?? map.getMaxZoom();
|
|
360
|
+
const zoom = map.getZoom();
|
|
361
|
+
const v = 1 / Math.pow(2, Math.max(0, Math.min(maxZoom - zoom, 12)));
|
|
362
|
+
const bounds = map.getBounds();
|
|
363
|
+
const padLat = r / size.y * (bounds.getNorth() - bounds.getSouth());
|
|
364
|
+
const padLng = r / size.x * (bounds.getEast() - bounds.getWest());
|
|
365
|
+
const paddedBounds = L2.latLngBounds(
|
|
366
|
+
[bounds.getSouth() - padLat, bounds.getWest() - padLng],
|
|
367
|
+
[bounds.getNorth() + padLat, bounds.getEast() + padLng]
|
|
368
|
+
);
|
|
369
|
+
let autoMax = 0;
|
|
370
|
+
if (this._options.max === void 0) {
|
|
371
|
+
for (const p of this._latlngs) {
|
|
372
|
+
const scaled = this._getIntensity(p) * v;
|
|
373
|
+
if (scaled > autoMax) autoMax = scaled;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
const effectiveMax = this._options.max ?? Math.max(autoMax, 1e-10);
|
|
377
|
+
const topLeft = map.containerPointToLayerPoint([0, 0]);
|
|
378
|
+
const grid = {};
|
|
379
|
+
const pixelPoints = [];
|
|
380
|
+
for (const p of this._latlngs) {
|
|
381
|
+
const latlng = this._toLatLng(p);
|
|
382
|
+
if (!paddedBounds.contains(latlng)) continue;
|
|
383
|
+
const lp = map.latLngToLayerPoint(latlng);
|
|
384
|
+
const x = lp.x - topLeft.x;
|
|
385
|
+
const y = lp.y - topLeft.y;
|
|
386
|
+
const intensity = this._getIntensity(p) * v;
|
|
387
|
+
const gx = Math.floor(lp.x / cellSize);
|
|
388
|
+
const gy = Math.floor(lp.y / cellSize);
|
|
389
|
+
const key = `${gx}:${gy}`;
|
|
390
|
+
const cell = grid[key];
|
|
391
|
+
if (cell) {
|
|
392
|
+
cell[0] += x * intensity;
|
|
393
|
+
cell[1] += y * intensity;
|
|
394
|
+
cell[2] += intensity;
|
|
395
|
+
cell[3]++;
|
|
396
|
+
} else {
|
|
397
|
+
grid[key] = [x * intensity, y * intensity, intensity, 1];
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
for (const key in grid) {
|
|
401
|
+
const cell = grid[key];
|
|
402
|
+
const totalIntensity = cell[2];
|
|
403
|
+
if (totalIntensity === 0) continue;
|
|
404
|
+
pixelPoints.push([
|
|
405
|
+
cell[0] / totalIntensity,
|
|
406
|
+
cell[1] / totalIntensity,
|
|
407
|
+
totalIntensity / effectiveMax
|
|
408
|
+
]);
|
|
409
|
+
}
|
|
410
|
+
renderer.draw(pixelPoints);
|
|
411
|
+
}
|
|
412
|
+
_getIntensity(p) {
|
|
413
|
+
if (p instanceof L2.LatLng) {
|
|
414
|
+
return p.alt ?? 1;
|
|
415
|
+
}
|
|
416
|
+
if (Array.isArray(p) && p.length >= 3) {
|
|
417
|
+
return p[2];
|
|
418
|
+
}
|
|
419
|
+
return 1;
|
|
420
|
+
}
|
|
421
|
+
_toLatLng(p) {
|
|
422
|
+
if (p instanceof L2.LatLng) return p;
|
|
423
|
+
return L2.latLng(p[0], p[1]);
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
// src/index.ts
|
|
428
|
+
function heatLayer(latlngs, options) {
|
|
429
|
+
return new HeatLayer(latlngs, options);
|
|
430
|
+
}
|
|
431
|
+
import_leaflet.default.heatLayer = heatLayer;
|
|
432
|
+
return __toCommonJS(index_exports);
|
|
433
|
+
})();
|
|
434
|
+
//# sourceMappingURL=leaflet-heatmap-layer.umd.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["leaflet-global:leaflet", "../src/index.ts", "../src/HeatLayer.ts", "../src/HeatRenderer.ts"],
|
|
4
|
+
"sourcesContent": ["module.exports = L;", "import L from 'leaflet';\nimport { HeatLayer, type HeatLayerOptions, type HeatLatLng } from './HeatLayer';\nimport { HeatRenderer, type HeatRendererOptions, type HeatPoint } from './HeatRenderer';\n\nfunction heatLayer(latlngs: HeatLatLng[], options?: HeatLayerOptions): HeatLayer {\n return new HeatLayer(latlngs, options);\n}\n\ndeclare module 'leaflet' {\n function heatLayer(latlngs: HeatLatLng[], options?: HeatLayerOptions): HeatLayer;\n}\n\n(L as any).heatLayer = heatLayer;\n\nexport {\n HeatLayer,\n HeatRenderer,\n heatLayer,\n type HeatLayerOptions,\n type HeatLatLng,\n type HeatRendererOptions,\n type HeatPoint,\n};\n", "import * as L from 'leaflet';\nimport { HeatRenderer, type HeatPoint } from './HeatRenderer';\n\nexport interface HeatLayerOptions extends L.LayerOptions {\n /** Radius of each heat point in pixels (default: 25). */\n radius?: number;\n /** Additional blur in pixels (default: 15). */\n blur?: number;\n /** Minimum opacity of the heatmap (default: 0.05). */\n minOpacity?: number;\n /** Zoom level at which points reach maximum intensity (default: map maxZoom or 18). */\n maxZoom?: number;\n /**\n * Manual maximum intensity cap. When omitted, computed automatically\n * per redraw from all data points \u2014 this is the core fix over Leaflet.heat.\n */\n max?: number;\n /** Color gradient stops (default: blue -> cyan -> lime -> yellow -> red). */\n gradient?: Record<number, string>;\n /** Duration in ms to crossfade between old and new heatmap on zoom (default: 250, 0 to disable). */\n zoomCrossfadeDuration?: number;\n}\n\n/** Input point: [lat, lng] or [lat, lng, intensity], or L.LatLng (with optional .alt for intensity). */\nexport type HeatLatLng = [number, number] | [number, number, number] | L.LatLng;\n\nexport class HeatLayer extends L.Layer {\n private _latlngs: HeatLatLng[];\n private _options: HeatLayerOptions;\n private _canvas: HTMLCanvasElement | null = null;\n private _renderer: HeatRenderer | null = null;\n private _frame: number | null = null;\n\n private _snapshotCanvas: HTMLCanvasElement | null = null;\n private _zooming = false;\n private _crossfadeTimer: number | null = null;\n\n constructor(latlngs: HeatLatLng[], options?: HeatLayerOptions) {\n super(options);\n this._latlngs = latlngs;\n this._options = {\n radius: 25,\n blur: 15,\n minOpacity: 0.05,\n ...options,\n };\n }\n\n onAdd(map: L.Map): this {\n this._map = map;\n\n if (!this._canvas) {\n this._createCanvas();\n }\n\n const pane = this.getPane();\n if (pane && this._canvas) {\n pane.appendChild(this._canvas);\n }\n\n map.on('moveend', this._onMoveEnd, this);\n map.on('zoomanim', this._onZoomAnim, this);\n\n this._onMoveEnd();\n return this;\n }\n\n onRemove(map: L.Map): this {\n if (this._frame !== null) {\n cancelAnimationFrame(this._frame);\n this._frame = null;\n }\n\n this._clearCrossfade();\n if (this._snapshotCanvas && this._snapshotCanvas.parentNode) {\n this._snapshotCanvas.parentNode.removeChild(this._snapshotCanvas);\n }\n this._snapshotCanvas = null;\n\n const pane = this.getPane();\n if (pane && this._canvas) {\n pane.removeChild(this._canvas);\n }\n\n map.off('moveend', this._onMoveEnd, this);\n map.off('zoomanim', this._onZoomAnim, this);\n\n return this;\n }\n\n /** Replace all data points and redraw. */\n setLatLngs(latlngs: HeatLatLng[]): this {\n this._latlngs = latlngs;\n return this.redraw();\n }\n\n /** Add a single data point and redraw. */\n addLatLng(latlng: HeatLatLng): this {\n this._latlngs.push(latlng);\n return this.redraw();\n }\n\n /** Update options and redraw. */\n setOptions(options: Partial<HeatLayerOptions>): this {\n Object.assign(this._options, options);\n if (this._renderer) {\n this._renderer.setOptions({\n radius: this._options.radius,\n blur: this._options.blur,\n minOpacity: this._options.minOpacity,\n gradient: this._options.gradient,\n });\n }\n return this.redraw();\n }\n\n /** Return a LatLngBounds covering all data points, or an invalid bounds if empty. */\n getBounds(): L.LatLngBounds {\n if (this._latlngs.length === 0) return L.latLngBounds([]);\n return L.latLngBounds(this._latlngs.map((p) => this._toLatLng(p)));\n }\n\n /** Schedule a redraw on the next animation frame. */\n redraw(): this {\n if (this._map && this._frame === null) {\n this._frame = requestAnimationFrame(() => {\n this._frame = null;\n this._redraw();\n });\n }\n return this;\n }\n\n private _createCanvas(): void {\n this._canvas = document.createElement('canvas');\n this._canvas.style.position = 'absolute';\n this._canvas.style.pointerEvents = 'none';\n this._canvas.style.willChange = 'transform';\n this._canvas.style.transformOrigin = '0 0';\n\n const animated = this._map!.options.zoomAnimation && L.Browser.any3d;\n L.DomUtil.addClass(\n this._canvas,\n 'leaflet-zoom-' + (animated ? 'animated' : 'hide'),\n );\n\n this._renderer = new HeatRenderer(this._canvas, {\n radius: this._options.radius,\n blur: this._options.blur,\n minOpacity: this._options.minOpacity,\n gradient: this._options.gradient,\n });\n }\n\n private _onMoveEnd(): void {\n if (!this._map || !this._canvas) return;\n\n const wasZooming = this._zooming;\n this._zooming = false;\n\n const duration = this._options.zoomCrossfadeDuration ?? 250;\n\n if (wasZooming && duration > 0) {\n this._takeSnapshot();\n }\n\n const size = this._map.getSize();\n const topLeft = this._map.containerPointToLayerPoint([0, 0]);\n\n L.DomUtil.setPosition(this._canvas, topLeft);\n this._renderer!.resize(size.x, size.y);\n\n this._redraw();\n\n if (wasZooming && duration > 0) {\n this._startCrossfade(duration);\n }\n }\n\n /** Apply CSS transform during zoom animation (same approach as Leaflet's ImageOverlay). */\n private _onZoomAnim(e: L.ZoomAnimEvent): void {\n if (!this._map || !this._canvas) return;\n\n this._zooming = true;\n\n const map = this._map;\n const scale = map.getZoomScale(e.zoom);\n const canvasPos = L.DomUtil.getPosition(this._canvas);\n const topLeftLatLng = map.layerPointToLatLng(canvasPos);\n\n const layerTopLeft = map.containerPointToLayerPoint([0, 0]);\n const newPos = map\n .project(topLeftLatLng, e.zoom)\n .subtract(map.project(e.center, e.zoom))\n .add(map.getSize().divideBy(2))\n .add(layerTopLeft)\n .round();\n\n L.DomUtil.setTransform(this._canvas, newPos, scale);\n }\n\n private _takeSnapshot(): void {\n if (!this._canvas) return;\n\n this._clearCrossfade();\n const canvas = this._canvas;\n\n if (!this._snapshotCanvas) {\n this._snapshotCanvas = document.createElement('canvas');\n this._snapshotCanvas.style.position = 'absolute';\n this._snapshotCanvas.style.pointerEvents = 'none';\n }\n\n const snap = this._snapshotCanvas;\n snap.width = canvas.width;\n snap.height = canvas.height;\n snap.getContext('2d')!.drawImage(canvas, 0, 0);\n\n snap.style.transform = canvas.style.transform;\n snap.style.transformOrigin = canvas.style.transformOrigin;\n snap.style.opacity = '1';\n snap.style.transition = '';\n\n if (canvas.parentNode) {\n canvas.after(snap);\n }\n }\n\n private _startCrossfade(duration: number): void {\n const snap = this._snapshotCanvas;\n if (!snap) return;\n\n snap.style.transition = `opacity ${duration}ms ease-out`;\n\n // Force reflow so the transition triggers\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n snap.offsetHeight;\n\n snap.style.opacity = '0';\n\n this._crossfadeTimer = window.setTimeout(() => {\n this._crossfadeTimer = null;\n if (snap) {\n snap.style.transition = '';\n }\n }, duration);\n }\n\n private _clearCrossfade(): void {\n if (this._crossfadeTimer !== null) {\n clearTimeout(this._crossfadeTimer);\n this._crossfadeTimer = null;\n }\n if (this._snapshotCanvas) {\n this._snapshotCanvas.style.transition = '';\n this._snapshotCanvas.style.opacity = '0';\n }\n }\n\n private _redraw(): void {\n if (!this._map || !this._renderer || !this._canvas) return;\n\n const map = this._map;\n const size = map.getSize();\n if (size.x === 0 || size.y === 0) return;\n const renderer = this._renderer;\n const r = renderer.radius + renderer.blur;\n const cellSize = Math.max(1, Math.floor(renderer.radius / 2));\n const maxZoom = this._options.maxZoom ?? map.getMaxZoom();\n const zoom = map.getZoom();\n\n // At maxZoom intensity is full, at lower zooms it tapers exponentially\n const v = 1 / Math.pow(2, Math.max(0, Math.min(maxZoom - zoom, 12)));\n\n const bounds = map.getBounds();\n const padLat = (r / size.y) * (bounds.getNorth() - bounds.getSouth());\n const padLng = (r / size.x) * (bounds.getEast() - bounds.getWest());\n const paddedBounds = L.latLngBounds(\n [bounds.getSouth() - padLat, bounds.getWest() - padLng],\n [bounds.getNorth() + padLat, bounds.getEast() + padLng],\n );\n\n // Compute auto-max across ALL points (not just visible) \u2014 this is the\n // core fix for the intensity/zoom scaling bug in Leaflet.heat.\n let autoMax = 0;\n if (this._options.max === undefined) {\n for (const p of this._latlngs) {\n const scaled = this._getIntensity(p) * v;\n if (scaled > autoMax) autoMax = scaled;\n }\n }\n const effectiveMax = this._options.max ?? Math.max(autoMax, 1e-10);\n\n const topLeft = map.containerPointToLayerPoint([0, 0]);\n\n // Grid-cluster visible points. Grid keys use layer-space coordinates\n // (stable across pans) to avoid flickering when cells shift on pan.\n const grid: Record<string, [number, number, number, number]> = {};\n const pixelPoints: HeatPoint[] = [];\n\n for (const p of this._latlngs) {\n const latlng = this._toLatLng(p);\n if (!paddedBounds.contains(latlng)) continue;\n\n const lp = map.latLngToLayerPoint(latlng);\n const x = lp.x - topLeft.x;\n const y = lp.y - topLeft.y;\n const intensity = this._getIntensity(p) * v;\n\n const gx = Math.floor(lp.x / cellSize);\n const gy = Math.floor(lp.y / cellSize);\n const key = `${gx}:${gy}`;\n\n const cell = grid[key];\n if (cell) {\n cell[0] += x * intensity;\n cell[1] += y * intensity;\n cell[2] += intensity;\n cell[3]++;\n } else {\n grid[key] = [x * intensity, y * intensity, intensity, 1];\n }\n }\n\n for (const key in grid) {\n const cell = grid[key];\n const totalIntensity = cell[2];\n if (totalIntensity === 0) continue;\n\n pixelPoints.push([\n cell[0] / totalIntensity,\n cell[1] / totalIntensity,\n totalIntensity / effectiveMax,\n ]);\n }\n\n renderer.draw(pixelPoints);\n }\n\n private _getIntensity(p: HeatLatLng): number {\n if (p instanceof L.LatLng) {\n return (p as L.LatLng & { alt?: number }).alt ?? 1.0;\n }\n if (Array.isArray(p) && p.length >= 3) {\n return (p as [number, number, number])[2];\n }\n return 1.0;\n }\n\n private _toLatLng(p: HeatLatLng): L.LatLng {\n if (p instanceof L.LatLng) return p;\n return L.latLng(p[0], p[1]);\n }\n}\n", "export interface HeatRendererOptions {\n /** Radius of each heat point in pixels. */\n radius: number;\n /** Additional blur applied to each point in pixels. */\n blur: number;\n /** Minimum opacity of the heatmap output (0\u20131). */\n minOpacity: number;\n /** Color gradient stops, keyed by position (0\u20131). */\n gradient: Record<number, string>;\n}\n\n/** A pixel-space data point: [x, y, intensity]. */\nexport type HeatPoint = [number, number, number];\n\nconst DEFAULT_GRADIENT: Record<number, string> = {\n 0.4: 'blue',\n 0.6: 'cyan',\n 0.7: 'lime',\n 0.8: 'yellow',\n 1.0: 'red',\n};\n\nexport class HeatRenderer {\n private _canvas: HTMLCanvasElement;\n private _ctx: CanvasRenderingContext2D;\n\n private _circle: HTMLCanvasElement | null = null;\n private _palette: Uint8ClampedArray | null = null;\n\n private _radius: number;\n private _blur: number;\n private _minOpacity: number;\n private _gradient: Record<number, string>;\n\n constructor(canvas: HTMLCanvasElement, options?: Partial<HeatRendererOptions>) {\n this._canvas = canvas;\n const ctx = canvas.getContext('2d');\n if (!ctx) throw new Error('Could not get 2d context from canvas');\n this._ctx = ctx;\n\n this._radius = options?.radius ?? 25;\n this._blur = options?.blur ?? 15;\n this._minOpacity = options?.minOpacity ?? 0.05;\n this._gradient = options?.gradient ?? DEFAULT_GRADIENT;\n }\n\n setOptions(options: Partial<HeatRendererOptions>): void {\n if (options.radius !== undefined || options.blur !== undefined) {\n this._radius = options.radius ?? this._radius;\n this._blur = options.blur ?? this._blur;\n this._circle = null;\n }\n if (options.gradient !== undefined) {\n this._gradient = options.gradient;\n this._palette = null;\n }\n if (options.minOpacity !== undefined) {\n this._minOpacity = options.minOpacity;\n }\n }\n\n get radius(): number {\n return this._radius;\n }\n\n get blur(): number {\n return this._blur;\n }\n\n resize(width: number, height: number): void {\n this._canvas.width = width;\n this._canvas.height = height;\n }\n\n clear(): void {\n this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);\n }\n\n /** Draw the heatmap. Intensity values should be pre-normalized to 0\u20131. */\n draw(points: HeatPoint[]): void {\n if (points.length === 0) {\n this.clear();\n return;\n }\n\n const circle = this._getCircle();\n const fullRadius = this._radius + this._blur;\n\n this.clear();\n\n for (const [x, y, intensity] of points) {\n this._ctx.globalAlpha = Math.max(intensity, this._minOpacity);\n this._ctx.drawImage(circle, x - fullRadius, y - fullRadius);\n }\n\n this._colorize();\n }\n\n private _getCircle(): HTMLCanvasElement {\n if (this._circle) return this._circle;\n\n const r = this._radius;\n const blur = this._blur;\n const fullRadius = r + blur;\n const diameter = fullRadius * 2;\n\n const circle = document.createElement('canvas');\n circle.width = diameter;\n circle.height = diameter;\n const ctx = circle.getContext('2d')!;\n\n ctx.shadowOffsetX = diameter;\n ctx.shadowOffsetY = diameter;\n ctx.shadowBlur = blur;\n ctx.shadowColor = 'black';\n\n ctx.beginPath();\n ctx.arc(fullRadius - diameter, fullRadius - diameter, r, 0, Math.PI * 2, true);\n ctx.closePath();\n ctx.fill();\n\n this._circle = circle;\n return circle;\n }\n\n private _getPalette(): Uint8ClampedArray {\n if (this._palette) return this._palette;\n\n const paletteCanvas = document.createElement('canvas');\n paletteCanvas.width = 256;\n paletteCanvas.height = 1;\n const ctx = paletteCanvas.getContext('2d')!;\n\n const grad = ctx.createLinearGradient(0, 0, 256, 0);\n for (const [stop, color] of Object.entries(this._gradient)) {\n grad.addColorStop(Number(stop), color);\n }\n ctx.fillStyle = grad;\n ctx.fillRect(0, 0, 256, 1);\n\n this._palette = ctx.getImageData(0, 0, 256, 1).data;\n return this._palette;\n }\n\n /** Map alpha channel (greyscale intensity) to gradient colors. */\n private _colorize(): void {\n const w = this._canvas.width;\n const h = this._canvas.height;\n if (w === 0 || h === 0) return;\n\n const imageData = this._ctx.getImageData(0, 0, w, h);\n const pixels = imageData.data;\n const palette = this._getPalette();\n\n for (let i = 0, len = pixels.length; i < len; i += 4) {\n const alpha = pixels[i + 3];\n if (alpha === 0) continue;\n\n const paletteOffset = alpha * 4;\n pixels[i] = palette[paletteOffset];\n pixels[i + 1] = palette[paletteOffset + 1];\n pixels[i + 2] = palette[paletteOffset + 2];\n // Keep original alpha to preserve the soft falloff from the blurred stamp\n }\n\n this._ctx.putImageData(imageData, 0, 0);\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["L", "L"]
|
|
7
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "leaflet-heatmap-layer",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A modern heatmap layer plugin for Leaflet",
|
|
5
|
+
"main": "dist/leaflet-heatmap-layer.cjs.js",
|
|
6
|
+
"module": "dist/leaflet-heatmap-layer.esm.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/leaflet-heatmap-layer.esm.js",
|
|
12
|
+
"require": "./dist/leaflet-heatmap-layer.cjs.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist/",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"sideEffects": true,
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "node build.mjs && tsc --emitDeclarationOnly",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"test:watch": "vitest",
|
|
24
|
+
"demo": "node build.mjs && cp dist/leaflet-heatmap-layer.umd.js docs/ && npx serve docs",
|
|
25
|
+
"demo:watch": "node dev-server.mjs",
|
|
26
|
+
"prepublishOnly": "npm run build"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"leaflet": "^1.0.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/leaflet": "^1.9.8",
|
|
33
|
+
"esbuild": "^0.27.3",
|
|
34
|
+
"jsdom": "^24.0.0",
|
|
35
|
+
"leaflet": "^1.9.4",
|
|
36
|
+
"tslib": "^2.6.2",
|
|
37
|
+
"typescript": "^5.3.3",
|
|
38
|
+
"vitest": "^1.2.0"
|
|
39
|
+
},
|
|
40
|
+
"keywords": [
|
|
41
|
+
"leaflet",
|
|
42
|
+
"heatmap",
|
|
43
|
+
"leaflet-plugin",
|
|
44
|
+
"maps",
|
|
45
|
+
"visualization",
|
|
46
|
+
"canvas"
|
|
47
|
+
],
|
|
48
|
+
"author": "koljam",
|
|
49
|
+
"license": "MIT",
|
|
50
|
+
"homepage": "https://github.com/koljam/leaflet-heatmap-layer#readme",
|
|
51
|
+
"bugs": {
|
|
52
|
+
"url": "https://github.com/koljam/leaflet-heatmap-layer/issues"
|
|
53
|
+
},
|
|
54
|
+
"repository": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": "git+https://github.com/koljam/leaflet-heatmap-layer.git"
|
|
57
|
+
}
|
|
58
|
+
}
|