diff --git a/debug/map/grid.html b/debug/map/grid.html
index 06e71d7f..fb733830 100644
--- a/debug/map/grid.html
+++ b/debug/map/grid.html
@@ -31,7 +31,7 @@
// test async
setTimeout(function () {
- done(tile);
+ done(null, tile);
}, Math.random() * 500);
return tile;
diff --git a/src/geo/crs/CRS.EPSG3857.js b/src/geo/crs/CRS.EPSG3857.js
index 670ca49a..6d668b79 100644
--- a/src/geo/crs/CRS.EPSG3857.js
+++ b/src/geo/crs/CRS.EPSG3857.js
@@ -14,6 +14,8 @@ L.CRS.EPSG3857 = L.extend({}, L.CRS, {
return new L.Transformation(scale, 0.5, -scale, 0.5);
}())
+
+ wrapLng: true
});
L.CRS.EPSG900913 = L.extend({}, L.CRS.EPSG3857, {
diff --git a/src/layer/tile/GridLayer.js b/src/layer/tile/GridLayer.js
index 1bae8154..66bce929 100644
--- a/src/layer/tile/GridLayer.js
+++ b/src/layer/tile/GridLayer.js
@@ -108,15 +108,6 @@ L.GridLayer = L.Class.extend({
return this;
},
- isValidTile: function (coords) {
- if (!this.options.bounds) { return true; }
-
- var tileBounds = this._tileCoordsToBounds(coords),
- bounds = L.latLngBounds(this.options.bounds);
-
- return bounds.contains(tileBounds);
- },
-
_getPane: function () {
// TODO pane in options?
return this._map._panes.tilePane;
@@ -274,7 +265,7 @@ L.GridLayer = L.Class.extend({
coords = new L.Point(i, j);
coords.z = zoom;
- if (!this._tileIsAdded(coords) && this.isValidTile(coords)) {
+ if (!this._tileIsAdded(coords) && this._isValidTile(coords)) {
queue.push(coords);
}
}
@@ -305,6 +296,21 @@ L.GridLayer = L.Class.extend({
this._tileContainer.appendChild(fragment);
},
+ _isValidTile: function (coords) {
+ var crs = this._map.options.crs,
+ limit = this._getWrapTileNum();
+
+ if (!crs.wrapLng && (coords.x < 0 || coords.x >= limit.x)) { return; }
+ if (!crs.wrapLat && (coords.y < 0 || coords.y >= limit.y)) { return; }
+
+ if (!this.options.bounds) { return true; }
+
+ var tileBounds = this._tileCoordsToBounds(coords),
+ bounds = L.latLngBounds(this.options.bounds);
+
+ return bounds.contains(tileBounds);
+ },
+
_tileIsAdded: function (coords) {
return this._tileCoordsToKey(coords) in this._tiles;
},
@@ -319,8 +325,6 @@ L.GridLayer = L.Class.extend({
nw = this._map.unproject(nwPoint),
se = this._map.unproject(sePoint);
- // TODO rectangular
-
return new L.LatLngBounds(nw, se);
},
@@ -379,19 +383,23 @@ L.GridLayer = L.Class.extend({
},
_addTile: function (coords, container) {
+ var tilePos = this._getTilePos(coords);
+
+ this._wrapCoords(coords);
+
var tile = this.createTile(coords, this._tileReady);
- // TODO wrapping happens here?
+ this.fire('tileloadstart', {tile: tile});
this._initTile(tile);
+ // if createTile is defined with a second argument ("done" callback),
+ // we know that tile is async and will be ready later; otherwise
if (this.createTile.length < 2) {
- // if tiles are sync, delay one frame for opacity anim to happen
- setTimeout(L.bind(this._tileReady, this, tile), 0);
+ // mark tile as ready, but delay one frame for opacity anim to happen
+ setTimeout(L.bind(this._tileReady, this, null, tile), 0);
}
- var tilePos = this._getTilePos(coords);
-
/*
Chrome 20 layouts much faster with top/left (verify with timeline, frames)
Android 4 browser has display issues with top/left and requires transform instead
@@ -406,7 +414,11 @@ L.GridLayer = L.Class.extend({
container.appendChild(tile);
},
- _tileReady: function (tile) {
+ _tileReady: function (err, tile) {
+ if (err) {
+ this.fire('tileerror', {error: err});
+ }
+
L.DomUtil.addClass(tile, 'leaflet-tile-loaded');
this.fire('tileload', {tile: tile});
@@ -435,6 +447,23 @@ L.GridLayer = L.Class.extend({
return tilePoint.multiplyBy(tileSize).subtract(origin);
},
+ _wrapCoords: function (coords) {
+ var crs = this._map.options.crs,
+ limit = this._getWrapTileNum();
+
+ if (crs.wrapLng) {
+ coords.x = ((coords.x % limit.x) + limit.x) % limit.x;
+ }
+ if (crs.wrapLat) {
+ coords.y = ((coords.y % limit.y) + limit.y) % limit.y;
+ }
+ },
+
+ _getWrapTileNum: function () {
+ var size = this._map.options.crs.getSize(this._map.getZoom());
+ return size.divideBy(this.options.tileSize);
+ },
+
_animateZoom: function (e) {
if (!this._animating) {
this._animating = true;