UNPKG

leaflet

Version:

JavaScript library for mobile-friendly interactive maps

161 lines (124 loc) 3.85 kB
/* * L.TileLayer is used for standard xyz-numbered tile layers. */ L.TileLayer = L.GridLayer.extend({ options: { maxZoom: 18, subdomains: 'abc', errorTileUrl: '', zoomOffset: 0, maxNativeZoom: null, // Number tms: false, zoomReverse: false, detectRetina: false, crossOrigin: false }, initialize: function (url, options) { this._url = url; options = L.setOptions(this, options); // detecting retina displays, adjusting tileSize and zoom levels if (options.detectRetina && L.Browser.retina && options.maxZoom > 0) { options.tileSize = Math.floor(options.tileSize / 2); options.zoomOffset++; options.minZoom = Math.max(0, options.minZoom); options.maxZoom--; } if (typeof options.subdomains === 'string') { options.subdomains = options.subdomains.split(''); } // for https://github.com/Leaflet/Leaflet/issues/137 if (!L.Browser.android) { this.on('tileunload', this._onTileRemove); } }, setUrl: function (url, noRedraw) { this._url = url; if (!noRedraw) { this.redraw(); } return this; }, createTile: function (coords, done) { var tile = document.createElement('img'); L.DomEvent.on(tile, 'load', L.bind(this._tileOnLoad, this, done, tile)); L.DomEvent.on(tile, 'error', L.bind(this._tileOnError, this, done, tile)); if (this.options.crossOrigin) { tile.crossOrigin = ''; } /* Alt tag is set to empty string to keep screen readers from reading URL and for compliance reasons http://www.w3.org/TR/WCAG20-TECHS/H67 */ tile.alt = ''; tile.src = this.getTileUrl(coords); return tile; }, getTileUrl: function (coords) { return L.Util.template(this._url, L.extend({ r: this.options.detectRetina && L.Browser.retina && this.options.maxZoom > 0 ? '@2x' : '', s: this._getSubdomain(coords), x: coords.x, y: this.options.tms ? this._globalTileRange.max.y - coords.y : coords.y, z: this._getZoomForUrl() }, this.options)); }, _tileOnLoad: function (done, tile) { // For https://github.com/Leaflet/Leaflet/issues/3332 if (L.Browser.ielt9) { setTimeout(L.bind(done, this, null, tile), 0); } else { done(null, tile); } }, _tileOnError: function (done, tile, e) { var errorUrl = this.options.errorTileUrl; if (errorUrl) { tile.src = errorUrl; } done(e, tile); }, getTileSize: function () { var map = this._map, tileSize = L.GridLayer.prototype.getTileSize.call(this), zoom = this._tileZoom + this.options.zoomOffset, zoomN = this.options.maxNativeZoom; // increase tile size when overscaling return zoomN !== null && zoom > zoomN ? tileSize.divideBy(map.getZoomScale(zoomN, zoom)).round() : tileSize; }, _onTileRemove: function (e) { e.tile.onload = null; }, _getZoomForUrl: function () { var options = this.options, zoom = this._tileZoom; if (options.zoomReverse) { zoom = options.maxZoom - zoom; } zoom += options.zoomOffset; return options.maxNativeZoom !== null ? Math.min(zoom, options.maxNativeZoom) : zoom; }, _getSubdomain: function (tilePoint) { var index = Math.abs(tilePoint.x + tilePoint.y) % this.options.subdomains.length; return this.options.subdomains[index]; }, // stops loading all tiles in the background layer _abortLoading: function () { var i, tile; for (i in this._tiles) { if (this._tiles[i].coords.z !== this._tileZoom) { tile = this._tiles[i].el; tile.onload = L.Util.falseFn; tile.onerror = L.Util.falseFn; if (!tile.complete) { tile.src = L.Util.emptyImageUrl; L.DomUtil.remove(tile); } } } } }); L.tileLayer = function (url, options) { return new L.TileLayer(url, options); };