TileLayer refactoring, add loading event, update changelog, closes #177
This commit is contained in:
parent
55c35828a8
commit
c50aaabd6d
@ -60,6 +60,7 @@ Icon API was improved to be more flexible, but one of the changes is backwards-i
|
|||||||
#### Other breaking API changes
|
#### Other breaking API changes
|
||||||
|
|
||||||
* Improved `TileLayer` constructor to interpolate URL template values from options (removed third `urlParams` argument).
|
* Improved `TileLayer` constructor to interpolate URL template values from options (removed third `urlParams` argument).
|
||||||
|
* Changed `TileLayer` `scheme: 'tms'` option to `tms: true`.
|
||||||
* Replaced ugly control position constants (e.g. `L.Control.Position.TOP_LEFT`) with light strings (`'topleft'`, `'bottomright'`, etc.)
|
* Replaced ugly control position constants (e.g. `L.Control.Position.TOP_LEFT`) with light strings (`'topleft'`, `'bottomright'`, etc.)
|
||||||
* Removed `Map` `locateAndSetView` method (use `locate` with `setView: true` option)
|
* Removed `Map` `locateAndSetView` method (use `locate` with `setView: true` option)
|
||||||
* Changed popup `minWidth` and `maxWidth` options to be applied to content element, not the whole popup.
|
* Changed popup `minWidth` and `maxWidth` options to be applied to content element, not the whole popup.
|
||||||
@ -73,6 +74,7 @@ Icon API was improved to be more flexible, but one of the changes is backwards-i
|
|||||||
* Added `TileLayer` `redraw` method for re-requesting tiles (by [@greeninfo](https://github.com/greeninfo)). [#719](https://github.com/CloudMade/Leaflet/issues/719)
|
* Added `TileLayer` `redraw` method for re-requesting tiles (by [@greeninfo](https://github.com/greeninfo)). [#719](https://github.com/CloudMade/Leaflet/issues/719)
|
||||||
* Added `TileLayer` `setUrl` method for dynamically changing the tile URL template.
|
* Added `TileLayer` `setUrl` method for dynamically changing the tile URL template.
|
||||||
* Added `bringToFront` and `bringToBack` methods to `TileLayer` and vector layers. [#185](https://github.com/CloudMade/Leaflet/issues/185) [#505](https://github.com/CloudMade/Leaflet/issues/505)
|
* Added `bringToFront` and `bringToBack` methods to `TileLayer` and vector layers. [#185](https://github.com/CloudMade/Leaflet/issues/185) [#505](https://github.com/CloudMade/Leaflet/issues/505)
|
||||||
|
* Added `TileLayer` `loading` event that fires when its tiles start to load (thanks to [@lapinos03](https://github.com/lapinos03)). [#177](https://github.com/CloudMade/Leaflet/issues/177)
|
||||||
* Added `TileLayer.WMS` `setParams` method for setting WMS parameters at runtime (by [@greeninfo](https://github.com/greeninfo)). [#719](https://github.com/CloudMade/Leaflet/issues/719)
|
* Added `TileLayer.WMS` `setParams` method for setting WMS parameters at runtime (by [@greeninfo](https://github.com/greeninfo)). [#719](https://github.com/CloudMade/Leaflet/issues/719)
|
||||||
* Added `TileLayer.WMS` subdomain support (`{s}` in the url) (by [@greeninfo](https://github.com/greeninfo)). [#735](https://github.com/CloudMade/Leaflet/issues/735)
|
* Added `TileLayer.WMS` subdomain support (`{s}` in the url) (by [@greeninfo](https://github.com/greeninfo)). [#735](https://github.com/CloudMade/Leaflet/issues/735)
|
||||||
* Added `originalEvent` property to `MouseEvent` (by [@k4](https://github.com/k4)). [#521](https://github.com/CloudMade/Leaflet/pull/521)
|
* Added `originalEvent` property to `MouseEvent` (by [@k4](https://github.com/k4)). [#521](https://github.com/CloudMade/Leaflet/pull/521)
|
||||||
@ -118,7 +120,7 @@ Icon API was improved to be more flexible, but one of the changes is backwards-i
|
|||||||
* Fixed a bug where `TileLayer` `setOpacity` wouldn't work when setting it back to 1.
|
* Fixed a bug where `TileLayer` `setOpacity` wouldn't work when setting it back to 1.
|
||||||
* Fixed a bug where vector layer `setStyle({stroke: false})` wouldn't remove stroke and the same for fill. [#441](https://github.com/CloudMade/Leaflet/issues/441)
|
* Fixed a bug where vector layer `setStyle({stroke: false})` wouldn't remove stroke and the same for fill. [#441](https://github.com/CloudMade/Leaflet/issues/441)
|
||||||
* Fixed a bug where `Marker` `bindPopup` method wouldn't take `offset` option into account.
|
* Fixed a bug where `Marker` `bindPopup` method wouldn't take `offset` option into account.
|
||||||
* Fixed a bug where `TileLayer` `load` event wasn't fired if some tile didn't load (by [@cfis](https://github.com/cfis)) [#682](https://github.com/CloudMade/Leaflet/pull/682)
|
* Fixed a bug where `TileLayer` `load` event wasn't fired if some tile didn't load (by [@lapinos03](https://github.com/lapinos03) and [@cfis](https://github.com/cfis)) [#682](https://github.com/CloudMade/Leaflet/pull/682)
|
||||||
* Fixed error when removing `GeoJSON` layer. [#685](https://github.com/CloudMade/Leaflet/issues/685)
|
* Fixed error when removing `GeoJSON` layer. [#685](https://github.com/CloudMade/Leaflet/issues/685)
|
||||||
* Fixed error when calling `GeoJSON` `clearLayer` (by [@runderwood](https://github.com/runderwood)). [#617](https://github.com/CloudMade/Leaflet/pull/617)
|
* Fixed error when calling `GeoJSON` `clearLayer` (by [@runderwood](https://github.com/runderwood)). [#617](https://github.com/CloudMade/Leaflet/pull/617)
|
||||||
* Fixed a bug where polygons/polylines sometimes throwed an error when making them editable manually (by [@cfis](https://github.com/cfis)). [#669](https://github.com/CloudMade/Leaflet/pull/669)
|
* Fixed a bug where polygons/polylines sometimes throwed an error when making them editable manually (by [@cfis](https://github.com/cfis)). [#669](https://github.com/CloudMade/Leaflet/pull/669)
|
||||||
|
@ -13,7 +13,7 @@ L.TileLayer = L.Class.extend({
|
|||||||
errorTileUrl: '',
|
errorTileUrl: '',
|
||||||
attribution: '',
|
attribution: '',
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
scheme: 'xyz',
|
tms: false,
|
||||||
continuousWorld: false,
|
continuousWorld: false,
|
||||||
noWrap: false,
|
noWrap: false,
|
||||||
zoomOffset: 0,
|
zoomOffset: 0,
|
||||||
@ -192,6 +192,7 @@ L.TileLayer = L.Class.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._tiles = {};
|
this._tiles = {};
|
||||||
|
this._tilesToLoad = 0;
|
||||||
|
|
||||||
if (this.options.reuseTiles) {
|
if (this.options.reuseTiles) {
|
||||||
this._unusedTiles = [];
|
this._unusedTiles = [];
|
||||||
@ -234,16 +235,21 @@ L.TileLayer = L.Class.extend({
|
|||||||
var queue = [],
|
var queue = [],
|
||||||
center = bounds.getCenter();
|
center = bounds.getCenter();
|
||||||
|
|
||||||
var j, i;
|
var j, i, point;
|
||||||
|
|
||||||
for (j = bounds.min.y; j <= bounds.max.y; j++) {
|
for (j = bounds.min.y; j <= bounds.max.y; j++) {
|
||||||
for (i = bounds.min.x; i <= bounds.max.x; i++) {
|
for (i = bounds.min.x; i <= bounds.max.x; i++) {
|
||||||
if (!((i + ':' + j) in this._tiles)) {
|
point = new L.Point(i, j);
|
||||||
queue.push(new L.Point(i, j));
|
|
||||||
|
if (this._tileShouldBeLoaded(point)) {
|
||||||
|
queue.push(point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queue.length === 0) { return; }
|
var tilesToLoad = queue.length;
|
||||||
|
|
||||||
|
if (tilesToLoad === 0) { return; }
|
||||||
|
|
||||||
// load tiles in order of their distance to center
|
// load tiles in order of their distance to center
|
||||||
queue.sort(function (a, b) {
|
queue.sort(function (a, b) {
|
||||||
@ -252,16 +258,37 @@ L.TileLayer = L.Class.extend({
|
|||||||
|
|
||||||
var fragment = document.createDocumentFragment();
|
var fragment = document.createDocumentFragment();
|
||||||
|
|
||||||
this._tilesToLoad = queue.length;
|
// if its the first batch of tiles to load
|
||||||
|
if (!this._tilesToLoad) {
|
||||||
|
this.fire('loading');
|
||||||
|
}
|
||||||
|
|
||||||
var k, len;
|
this._tilesToLoad += tilesToLoad;
|
||||||
for (k = 0, len = this._tilesToLoad; k < len; k++) {
|
|
||||||
this._addTile(queue[k], fragment);
|
for (i = 0; i < tilesToLoad; i++) {
|
||||||
|
this._addTile(queue[i], fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._container.appendChild(fragment);
|
this._container.appendChild(fragment);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_tileShouldBeLoaded: function (tilePoint) {
|
||||||
|
if ((tilePoint.x + ':' + tilePoint.y) in this._tiles) {
|
||||||
|
return false; // already loaded
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.options.continuousWorld) {
|
||||||
|
var limit = this._getWrapTileNum();
|
||||||
|
|
||||||
|
if (this.options.noWrap && (tilePoint.x < 0 || tilePoint.x >= limit) ||
|
||||||
|
tilePoint.y < 0 || tilePoint.y >= limit) {
|
||||||
|
return false; // exceeds world bounds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
_removeOtherTiles: function (bounds) {
|
_removeOtherTiles: function (bounds) {
|
||||||
var kArr, x, y, key;
|
var kArr, x, y, key;
|
||||||
|
|
||||||
@ -299,25 +326,7 @@ L.TileLayer = L.Class.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_addTile: function (tilePoint, container) {
|
_addTile: function (tilePoint, container) {
|
||||||
var tilePos = this._getTilePos(tilePoint),
|
var tilePos = this._getTilePos(tilePoint);
|
||||||
zoom = this._map.getZoom(),
|
|
||||||
key = tilePoint.x + ':' + tilePoint.y,
|
|
||||||
limit = Math.pow(2, this._getOffsetZoom(zoom));
|
|
||||||
|
|
||||||
// wrap tile coordinates
|
|
||||||
if (!this.options.continuousWorld) {
|
|
||||||
if (!this.options.noWrap) {
|
|
||||||
tilePoint.x = ((tilePoint.x % limit) + limit) % limit;
|
|
||||||
} else if (tilePoint.x < 0 || tilePoint.x >= limit) {
|
|
||||||
this._tilesToLoad--;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tilePoint.y < 0 || tilePoint.y >= limit) {
|
|
||||||
this._tilesToLoad--;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get unused tile - or create a new tile
|
// get unused tile - or create a new tile
|
||||||
var tile = this._getTile();
|
var tile = this._getTile();
|
||||||
@ -327,22 +336,24 @@ L.TileLayer = L.Class.extend({
|
|||||||
// (other browsers don't currently care) - see debug/hacks/jitter.html for an example
|
// (other browsers don't currently care) - see debug/hacks/jitter.html for an example
|
||||||
L.DomUtil.setPosition(tile, tilePos, L.Browser.chrome);
|
L.DomUtil.setPosition(tile, tilePos, L.Browser.chrome);
|
||||||
|
|
||||||
this._tiles[key] = tile;
|
this._tiles[tilePoint.x + ':' + tilePoint.y] = tile;
|
||||||
|
|
||||||
if (this.options.scheme === 'tms') {
|
this._loadTile(tile, tilePoint);
|
||||||
tilePoint.y = limit - tilePoint.y - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._loadTile(tile, tilePoint, zoom);
|
|
||||||
|
|
||||||
if (tile.parentNode !== this._container) {
|
if (tile.parentNode !== this._container) {
|
||||||
container.appendChild(tile);
|
container.appendChild(tile);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_getOffsetZoom: function (zoom) {
|
_getZoomForUrl: function () {
|
||||||
var options = this.options;
|
|
||||||
zoom = options.zoomReverse ? options.maxZoom - zoom : zoom;
|
var options = this.options,
|
||||||
|
zoom = this._map.getZoom();
|
||||||
|
|
||||||
|
if (options.zoomReverse) {
|
||||||
|
zoom = options.maxZoom - zoom;
|
||||||
|
}
|
||||||
|
|
||||||
return zoom + options.zoomOffset;
|
return zoom + options.zoomOffset;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -355,15 +366,34 @@ L.TileLayer = L.Class.extend({
|
|||||||
|
|
||||||
// image-specific code (override to implement e.g. Canvas or SVG tile layer)
|
// image-specific code (override to implement e.g. Canvas or SVG tile layer)
|
||||||
|
|
||||||
getTileUrl: function (tilePoint, zoom) {
|
getTileUrl: function (tilePoint) {
|
||||||
|
this._adjustTilePoint(tilePoint);
|
||||||
|
|
||||||
return L.Util.template(this._url, L.Util.extend({
|
return L.Util.template(this._url, L.Util.extend({
|
||||||
s: this._getSubdomain(tilePoint),
|
s: this._getSubdomain(tilePoint),
|
||||||
z: this._getOffsetZoom(zoom),
|
z: this._getZoomForUrl(),
|
||||||
x: tilePoint.x,
|
x: tilePoint.x,
|
||||||
y: tilePoint.y
|
y: tilePoint.y
|
||||||
}, this.options));
|
}, this.options));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_getWrapTileNum: function () {
|
||||||
|
// TODO refactor, limit is not valid for non-standard projections
|
||||||
|
return Math.pow(2, this._getZoomForUrl());
|
||||||
|
},
|
||||||
|
|
||||||
|
_adjustTilePoint: function (tilePoint) {
|
||||||
|
// wrap tile coordinates
|
||||||
|
if (!this.options.continuousWorld && !this.options.noWrap) {
|
||||||
|
var limit = this._getWrapTileNum();
|
||||||
|
tilePoint.x = ((tilePoint.x % limit) + limit) % limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.tms) {
|
||||||
|
tilePoint.y = limit - tilePoint.y - 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
_getSubdomain: function (tilePoint) {
|
_getSubdomain: function (tilePoint) {
|
||||||
var index = (tilePoint.x + tilePoint.y) % this.options.subdomains.length;
|
var index = (tilePoint.x + tilePoint.y) % this.options.subdomains.length;
|
||||||
return this.options.subdomains[index];
|
return this.options.subdomains[index];
|
||||||
@ -397,12 +427,12 @@ L.TileLayer = L.Class.extend({
|
|||||||
return tile;
|
return tile;
|
||||||
},
|
},
|
||||||
|
|
||||||
_loadTile: function (tile, tilePoint, zoom) {
|
_loadTile: function (tile, tilePoint) {
|
||||||
tile._layer = this;
|
tile._layer = this;
|
||||||
tile.onload = this._tileOnLoad;
|
tile.onload = this._tileOnLoad;
|
||||||
tile.onerror = this._tileOnError;
|
tile.onerror = this._tileOnError;
|
||||||
|
|
||||||
tile.src = this.getTileUrl(tilePoint, zoom);
|
tile.src = this.getTileUrl(tilePoint);
|
||||||
},
|
},
|
||||||
|
|
||||||
_tileLoaded: function () {
|
_tileLoaded: function () {
|
||||||
|
Loading…
Reference in New Issue
Block a user