UNPKG

heatmap-libs

Version:

Heatmap libraries including heatmap.js and Leaflet heatmap plugin

219 lines (175 loc) 6.54 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = global || self, factory(global.leafletHeatmap = {})); }(this, function (exports) { 'use strict'; var L = (typeof window !== "undefined" ? window.L : typeof global !== "undefined" ? global.L : null); var h337 = (typeof window !== "undefined" ? window.h337 : typeof global !== "undefined" ? global.h337 : null); if (!L) { throw new Error('Leaflet must be loaded before leaflet-heatmap'); } if (!h337) { throw new Error('heatmap.js must be loaded before leaflet-heatmap'); } var HeatmapOverlay = L.Layer.extend({ initialize: function (config) { this.cfg = config; this._el = L.DomUtil.create('div', 'leaflet-zoom-hide'); this._data = []; this._max = 1; this._min = 0; this.cfg.container = this._el; }, onAdd: function (map) { let size = map.getSize(); this._map = map; this._width = size.x; this._height = size.y; this._el.style.width = size.x + 'px'; this._el.style.height = size.y + 'px'; this._el.style.position = 'absolute'; this._origin = this._map.layerPointToLatLng(new L.Point(0, 0)); map.getPanes().overlayPane.appendChild(this._el); if (!this._heatmap) { this._heatmap = h337.create(this.cfg); } // this resets the origin and redraws whenever // the zoom changed or the map has been moved map.on('moveend', this._reset, this); this._draw(); }, onRemove: function (map) { // remove layer's DOM elements and listeners map.getPanes().overlayPane.removeChild(this._el); map.off('moveend', this._reset, this); }, _draw: function () { if (!this._map) { return; } let mapPane = this._map.getPanes().mapPane; let point = mapPane._leaflet_pos; // reposition the layer this._el.style[HeatmapOverlay.CSS_TRANSFORM] = 'translate(' + -Math.round(point.x) + 'px,' + -Math.round(point.y) + 'px)'; this._update(); }, _update: function () { let bounds, zoom, scale; let generatedData = { max: this._max, min: this._min, data: [] }; bounds = this._map.getBounds(); zoom = this._map.getZoom(); scale = Math.pow(2, zoom); if (this._data.length == 0) { if (this._heatmap) { this._heatmap.setData(generatedData); } return; } let latLngPoints = []; let radiusMultiplier = this.cfg.scaleRadius ? scale : 1; let localMax = 0; let localMin = 0; let valueField = this.cfg.valueField; let len = this._data.length; while (len--) { let entry = this._data[len]; let value = entry[valueField]; let latlng = entry.latlng; // we don't wanna render points that are not even on the map ;-) if (!bounds.contains(latlng)) { continue; } // local max is the maximum within current bounds localMax = Math.max(value, localMax); localMin = Math.min(value, localMin); let point = this._map.latLngToContainerPoint(latlng); let latlngPoint = { x: Math.round(point.x), y: Math.round(point.y) }; latlngPoint[valueField] = value; let radius; if (entry.radius) { radius = entry.radius * radiusMultiplier; } else { radius = (this.cfg.radius || 2) * radiusMultiplier; } latlngPoint.radius = radius; latLngPoints.push(latlngPoint); } if (this.cfg.useLocalExtrema) { generatedData.max = localMax; generatedData.min = localMin; } generatedData.data = latLngPoints; this._heatmap.setData(generatedData); }, setData: function (data) { this._max = data.max || this._max; this._min = data.min || this._min; let latField = this.cfg.latField || 'lat'; let lngField = this.cfg.lngField || 'lng'; let valueField = this.cfg.valueField || 'value'; // transform data to latlngs let len = data.length; let d = []; while (len--) { let entry = data[len]; let latlng = new L.LatLng(entry[latField], entry[lngField]); let dataObj = { latlng: latlng }; dataObj[valueField] = entry[valueField]; if (entry.radius) { dataObj.radius = entry.radius; } d.push(dataObj); } this._data = d; this._draw(); }, addData: function (pointOrArray) { if (pointOrArray.length > 0) { let len = pointOrArray.length; while (len--) { this.addData(pointOrArray[len]); } } else { let latField = this.cfg.latField || 'lat'; let lngField = this.cfg.lngField || 'lng'; let valueField = this.cfg.valueField || 'value'; let entry = pointOrArray; let latlng = new L.LatLng(entry[latField], entry[lngField]); let dataObj = { latlng: latlng }; dataObj[valueField] = entry[valueField]; this._max = Math.max(this._max, dataObj[valueField]); this._min = Math.min(this._min, dataObj[valueField]); if (entry.radius) { dataObj.radius = entry.radius; } this._data.push(dataObj); this._draw(); } }, _reset: function () { this._origin = this._map.layerPointToLatLng(new L.Point(0, 0)); let size = this._map.getSize(); if (this._width !== size.x || this._height !== size.y) { this._width = size.x; this._height = size.y; this._el.style.width = this._width + 'px'; this._el.style.height = this._height + 'px'; this._heatmap._renderer.setDimensions(this._width, this._height); } this._draw(); }, }); HeatmapOverlay.CSS_TRANSFORM = (function () { let div = document.createElement('div'); let props = ['transform', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform']; for (const prop of props) { if (div.style[prop] !== undefined) { return prop; } } return props[0]; })(); exports.HeatmapOverlay = HeatmapOverlay; }));