1(function (root, factory) { 2 if (typeof define === 'function' && define.amd) { 3 // AMD 4 define(['leaflet', 'maplibre-gl'], factory); 5 } else if (typeof exports === 'object') { 6 // Node, CommonJS-like 7 module.exports = factory(require('leaflet'), require('maplibre-gl')); 8 } else { 9 // Browser globals (root is window) 10 root.returnExports = factory(root.L, root.maplibregl); 11 } 12}(typeof globalThis !== 'undefined' ? globalThis : this || self, function (L, maplibregl) { 13 L.MaplibreGL = L.Layer.extend({ 14 options: { 15 updateInterval: 32, 16 // How much to extend the overlay view (relative to map size) 17 // e.g. 0.1 would be 10% of map view in each direction 18 padding: 0.1, 19 // whether or not to register the mouse and keyboard 20 // events on the maplibre overlay 21 interactive: false, 22 // set the tilepane as the default pane to draw gl tiles 23 pane: 'tilePane' 24 }, 25 26 initialize: function (options) { 27 L.setOptions(this, options); 28 29 // setup throttling the update event when panning 30 this._throttledUpdate = L.Util.throttle(this._update, this.options.updateInterval, this); 31 }, 32 33 onAdd: function (map) { 34 if (!this._container) { 35 this._initContainer(); 36 } 37 38 var paneName = this.getPaneName(); 39 map.getPane(paneName).appendChild(this._container); 40 41 this._initGL(); 42 43 this._offset = this._map.containerPointToLayerPoint([0, 0]); 44 45 // work around https://github.com/mapbox/mapbox-gl-leaflet/issues/47 46 if (map.options.zoomAnimation) { 47 L.DomEvent.on(map._proxy, L.DomUtil.TRANSITION_END, this._transitionEnd, this); 48 } 49 }, 50 51 onRemove: function (map) { 52 if (this._map._proxy && this._map.options.zoomAnimation) { 53 L.DomEvent.off(this._map._proxy, L.DomUtil.TRANSITION_END, this._transitionEnd, this); 54 } 55 var paneName = this.getPaneName(); 56 map.getPane(paneName).removeChild(this._container); 57 58 this._glMap.remove(); 59 this._glMap = null; 60 }, 61 62 getEvents: function () { 63 return { 64 move: this._throttledUpdate, // sensibly throttle updating while panning 65 zoomanim: this._animateZoom, // applys the zoom animation to the <canvas> 66 zoom: this._pinchZoom, // animate every zoom event for smoother pinch-zooming 67 zoomstart: this._zoomStart, // flag starting a zoom to disable panning 68 zoomend: this._zoomEnd, 69 resize: this._resize 70 }; 71 }, 72 73 // https://leafletjs.com/reference.html#layer-getattribution 74 getAttribution: function () { 75 // Return custom attribution if specified in options 76 if (this.options.attributionControl) { 77 return this.options.attributionControl.customAttribution; 78 } 79 80 // Gather attributions from MapLibre styles 81 var map = this._glMap; 82 if (map && this.options.attributionControl !== false) { 83 var style = map.getStyle(); 84 if (style && style.sources) { 85 return Object.keys(style.sources) 86 .map(function (sourceId) { 87 var source = map.getSource(sourceId); 88 return (source && typeof source.attribution === 'string') ? source.attribution.trim() : null; 89 }) 90 .filter(Boolean) // Remove null/undefined values 91 .join(', '); 92 } 93 } 94 95 return ''; 96 }, 97 98 getMaplibreMap: function () { 99 return this._glMap; 100 }, 101 102 getCanvas: function () { 103 return this._glMap.getCanvas(); 104 }, 105 106 getSize: function () { 107 return this._map.getSize().multiplyBy(1 + this.options.padding * 2); 108 }, 109 110 getBounds: function () { 111 var halfSize = this.getSize().multiplyBy(0.5); 112 var center = this._map.latLngToContainerPoint(this._map.getCenter()); 113 return L.latLngBounds( 114 this._map.containerPointToLatLng(center.subtract(halfSize)), 115 this._map.containerPointToLatLng(center.add(halfSize)) 116 ); 117 }, 118 119 getContainer: function () { 120 return this._container; 121 }, 122 123 // returns the pane name set in options if it is a valid pane, defaults to tilePane 124 getPaneName: function () { 125 return this._map.getPane(this.options.pane) ? this.options.pane : 'tilePane'; 126 }, 127 128 _roundPoint: function (p) { 129 return { x: Math.round(p.x), y: Math.round(p.y) }; 130 }, 131 132 _initContainer: function () { 133 var container = this._container = L.DomUtil.create('div', 'leaflet-gl-layer'); 134 this._resizeContainer(); 135 136 var offset = this._map.getSize().multiplyBy(this.options.padding); 137 138 var topLeft = this._map.containerPointToLayerPoint([0, 0]).subtract(offset); 139 140 L.DomUtil.setPosition(container, this._roundPoint(topLeft)); 141 }, 142 143 _resizeContainer: function () {
144 var size = this.getSize(); 145 this._container.style.width = size.x + 'px'; 146 this._container.style.height = size.y + 'px'; 147 }, 148 149 _initGL: function () { 150 var center = this._map.getCenter(); 151 152 var options = L.extend({}, this.options, { 153 container: this._container, 154 center: [center.lng, center.lat], 155 zoom: this._map.getZoom() - 1, 156 attributionControl: false 157 }); 158 159 this._glMap = new maplibregl.Map(options); 160 161 var _map = this._map; 162 var _currentAttribution = this.getAttribution(); 163 var _getAttribution = this.getAttribution.bind(this); 164 this._glMap.on('load', function () { 165 // Force attribution update 166 if (_map && _map.attributionControl) { 167 _map.attributionControl.removeAttribution(_currentAttribution); 168 _map.attributionControl.addAttribution(_getAttribution()); 169 } 170 }); 171 172 // allow GL base map to pan beyond min/max latitudes 173 // Defensively check if properties are writable before setting them, 174 // ensuring compatibility with both old and new versions of MapLibre GL JS. 175 var transformProto = Object.getPrototypeOf(this._glMap.transform); 176 177 var latRangeDescriptor = Object.getOwnPropertyDescriptor(transformProto, 'latRange'); 178 if (!latRangeDescriptor || latRangeDescriptor.set || latRangeDescriptor.writable) { 179 this._glMap.transform.latRange = null; 180 } 181 182 // Although this property is obsolete in modern versions, we apply the same 183 // defensive check for robust backward compatibility. 184 var maxValidLatitudeDescriptor = Object.getOwnPropertyDescriptor(transformProto, 'maxValidLatitude'); 185 if (!maxValidLatitudeDescriptor || maxValidLatitudeDescriptor.set || maxValidLatitudeDescriptor.writable) { 186 this._glMap.transform.maxValidLatitude = Infinity; 187 } 188 189 190 // check for the existence of _helper and _latRange in MapLibre 191 // this supports MapLibre v5 192 if (this._glMap.transform._helper && this._glMap.transform._helper._latRange) { 193 this._glMap.transform._helper._latRange = [-Infinity, Infinity]; 194 } 195 196 this._transformGL(this._glMap); 197 198 if (this._glMap._canvas.canvas) { 199 // older versions of mapbox-gl surfaced the canvas differently 200 this._glMap._actualCanvas = this._glMap._canvas.canvas; 201 } else { 202 this._glMap._actualCanvas = this._glMap._canvas; 203 } 204 205 206 // treat child <canvas> element like L.ImageOverlay 207 var canvas = this._glMap._actualCanvas; 208 L.DomUtil.addClass(canvas, 'leaflet-image-layer'); 209 L.DomUtil.addClass(canvas, 'leaflet-zoom-animated'); 210 211 if (this.options.interactive) { 212 L.DomUtil.addClass(canvas, 'leaflet-interactive'); 213 } 214 if (this.options.className) { 215 L.DomUtil.addClass(canvas, this.options.className); 216 } 217 }, 218 219 _update: function (e) { 220 if (!this._map) { 221 return; 222 } 223 // update the offset so we can correct for it later when we zoom 224 this._offset = this._map.containerPointToLayerPoint([0, 0]); 225 226 if (this._zooming) { 227 return; 228 } 229 230 var container = this._container, 231 gl = this._glMap, 232 offset = this._map.getSize().multiplyBy(this.options.padding), 233 topLeft = this._map.containerPointToLayerPoint([0, 0]).subtract(offset); 234 235 L.DomUtil.setPosition(container, this._roundPoint(topLeft)); 236 237 this._transformGL(gl); 238 }, 239 240 _transformGL: function (gl) { 241 var center = this._map.getCenter(); 242 243 // gl.setView([center.lat, center.lng], this._map.getZoom() - 1, 0); 244 // calling setView directly causes sync issues because it uses requestAnimFrame 245 246 var tr = gl._getTransformForUpdate(); // .clone() ? 247 248 if (tr.setCenter) { 249 // maplibre 5.0.0 and higher: 250 tr.setCenter(maplibregl.LngLat.convert([center.lng, center.lat])); 251 tr.setZoom(this._map.getZoom() - 1); 252 gl.transform.apply(tr); 253 } else { 254 // maplibre < 5.0.0 255 tr = gl.transform; 256 tr.center = maplibregl.LngLat.convert([center.lng, center.lat]); 257 tr.zoom = this._map.getZoom() - 1; 258 } 259 260 gl._fireMoveEvents(); 261 }, 262 263 // update the map constantly during a pinch zoom 264 _pinchZoom: function (e) { 265 this._glMap.jumpTo({ 266 zoom: this._map.getZoom() - 1, 267 center: this._map.getCenter() 268 }); 269 }, 270 271 // borrowed from L.ImageOverlay 272 // https://github.com/Leaflet/Leaflet/blob/master/src/layer/ImageOverlay.js#L139-L144 273 _animateZoom: function (e) { 274 var scale = this._map.getZoomScale(e.zoom); 275 var padding = this._map.getSize().multiplyBy(this.options.padding * scale);
276 var viewHalf = this.getSize()._divideBy(2); 277 // corrections for padding (scaled), adapted from 278 // https://github.com/Leaflet/Leaflet/blob/master/src/map/Map.js#L1490-L1508 279 var topLeft = this._map.project(e.center, e.zoom) 280 ._subtract(viewHalf) 281 ._add(this._map._getMapPanePos() 282 .add(padding))._round(); 283 var offset = this._map.project(this._map.getBounds().getNorthWest(), e.zoom) 284 ._subtract(topLeft); 285 286 L.DomUtil.setTransform( 287 this._glMap._actualCanvas, 288 offset.subtract(this._offset), 289 scale 290 ); 291 }, 292 293 _zoomStart: function (e) { 294 this._zooming = true; 295 }, 296 297 _zoomEnd: function () { 298 var scale = this._map.getZoomScale(this._map.getZoom()); 299 300 L.DomUtil.setTransform( 301 this._glMap._actualCanvas, 302 // https://github.com/mapbox/mapbox-gl-leaflet/pull/130 303 null, 304 scale 305 ); 306 307 this._zooming = false; 308 309 this._update(); 310 }, 311 312 _transitionEnd: function (e) { 313 L.Util.requestAnimFrame(function () { 314 var zoom = this._map.getZoom(); 315 var center = this._map.getCenter(); 316 var offset = this._map.latLngToContainerPoint( 317 this._map.getBounds().getNorthWest() 318 ); 319 this._resizeContainer(); 320 321 // reset the scale and offset 322 L.DomUtil.setTransform(this._glMap._actualCanvas, offset, 1); 323 324 // enable panning once the gl map is ready again 325 this._glMap.once('moveend', L.Util.bind(function () { 326 this._zoomEnd(); 327 }, this)); 328 329 // update the map position 330 this._glMap.jumpTo({ 331 center: center, 332 zoom: zoom - 1 333 }); 334 }, this); 335 }, 336 337 _resize: function (e) { 338 this._transitionEnd(e); 339 } 340 }); 341 342 L.maplibreGL = function (options) { 343 return new L.MaplibreGL(options); 344 }; 345 346}));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.