more TileLayer and Control.Layers zIndex improvements, #309

This commit is contained in:
Vladimir Agafonkin 2012-07-27 12:32:24 +03:00
parent 6142a8b74c
commit cdfaad994f
8 changed files with 157 additions and 63 deletions

View File

@ -20,8 +20,8 @@ Leaflet 0.4 contains several API improvements that allow simpler, jQuery-like sy
* Added configurable **panning inertia** - after a quick pan, the map slows down in the same direction.
* Added **polyline and polygon editing**. [#174](https://github.com/CloudMade/Leaflet/issues/174)
* Added an unobtrusive **scale control**.
* Added `DivIcon` class that easily allows you to create lightweight div-based markers.
* Added `Rectangle` vector layer (by [@JasonSanford](https://github.com/JasonSanford)). [#504](https://github.com/CloudMade/Leaflet/pull/504)
* Added **DivIcon** class that easily allows you to create lightweight div-based markers.
* Added **Rectangle** vector layer (by [@JasonSanford](https://github.com/JasonSanford)). [#504](https://github.com/CloudMade/Leaflet/pull/504)
* Added **Android 4+ pinch-zoom** support (by [@danzel](https://github.com/danzel)). [#774](https://github.com/CloudMade/Leaflet/pull/774)
### Improvements
@ -71,9 +71,11 @@ Icon API was improved to be more flexible, but one of the changes is backwards-i
* Improved `on` and `off` methods to also accept `(eventHash[, context])`, as well as multiple space-separated events (by [@Guiswa](https://github.com/Guiswa)). [#770](https://github.com/CloudMade/Leaflet/pull/770)
* Improved `off` to remove all listeners of the event if no function was specified (by [@Guiswa](https://github.com/Guiswa)). [#770](https://github.com/CloudMade/Leaflet/pull/770) [#691](https://github.com/CloudMade/Leaflet/issues/691)
* Added `TileLayer` `setZIndex` method for controlling the order of tile layers (thanks to [@mattcurrie](https://github.com/mattcurrie)). [#837](https://github.com/CloudMade/Leaflet/pull/837)
* Added `Control.Layers` `autoZIndex` option (on by default) to preserve the order of tile layers when switching.
* 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 `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`, `ImageOverlay` 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` subdomain support (`{s}` in the url) (by [@greeninfo](https://github.com/greeninfo)). [#735](https://github.com/CloudMade/Leaflet/issues/735)

View File

@ -17,9 +17,10 @@
<script type="text/javascript">
var map = new L.Map('map');
var cloudmadeUrl = 'http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png',
var cloudmadeUrl = 'http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/{styleId}/256/{z}/{x}/{y}.png',
cloudmadeAttribution = 'Map data &copy; 2011 OpenStreetMap contributors, Imagery &copy; 2011 CloudMade',
cloudmade = new L.TileLayer(cloudmadeUrl, {maxZoom: 18, attribution: cloudmadeAttribution});
cloudmade = new L.TileLayer(cloudmadeUrl, {styleId: 997, attribution: cloudmadeAttribution}),
cloudmade2 = new L.TileLayer(cloudmadeUrl, {styleId: 998, attribution: cloudmadeAttribution});
var nexrad = new L.TileLayer.WMS("http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi", {
layers: 'nexrad-n0r-900913',
@ -32,6 +33,8 @@
var bounds = new L.LatLngBounds(new L.LatLng(32, -126), new L.LatLng(50, -64));
map.addLayer(cloudmade).addLayer(nexrad).fitBounds(bounds);
L.control.layers({"CM": cloudmade, "CM2": cloudmade2}, {"NexRad": nexrad}).addTo(map);
</script>
</body>
</html>

99
dist/leaflet-src.js vendored
View File

@ -466,6 +466,16 @@ L.Point.prototype = {
return this;
},
floor: function () {
return this.clone()._floor();
},
_floor: function () {
this.x = Math.floor(this.x);
this.y = Math.floor(this.y);
return this;
},
clone: function () {
return new L.Point(this.x, this.y);
},
@ -1256,7 +1266,7 @@ L.Map = L.Class.extend({
return this.panBy(new L.Point(dx, dy, true));
},
addLayer: function (layer, insertAtTheBottom) {
addLayer: function (layer) {
// TODO method is too big, refactor
var id = L.Util.stamp(layer);
@ -1281,7 +1291,7 @@ L.Map = L.Class.extend({
}
var onMapLoad = function () {
layer.onAdd(this, insertAtTheBottom);
layer.onAdd(this);
this.fire('layeradd', {layer: layer});
};
@ -1858,17 +1868,19 @@ L.TileLayer = L.Class.extend({
subdomains: 'abc',
errorTileUrl: '',
attribution: '',
zoomOffset: 0,
opacity: 1,
/* (undefined works too)
zIndex: null,
tms: false,
continuousWorld: false,
noWrap: false,
zoomOffset: 0,
zoomReverse: false,
detectRetina: false,
reuseTiles: false,
*/
unloadInvisibleTiles: L.Browser.mobile,
updateWhenIdle: L.Browser.mobile,
reuseTiles: false
updateWhenIdle: L.Browser.mobile
},
initialize: function (url, options) {
@ -1895,9 +1907,8 @@ L.TileLayer = L.Class.extend({
}
},
onAdd: function (map, insertAtTheBottom) {
onAdd: function (map) {
this._map = map;
this._insertAtTheBottom = insertAtTheBottom;
// create a container div for tiles
this._initContainer();
@ -1942,17 +1953,24 @@ L.TileLayer = L.Class.extend({
},
bringToFront: function () {
var pane = this._map._panes.tilePane;
if (this._container) {
this._map._panes.tilePane.appendChild(this._container);
pane.appendChild(this._container);
this._setAutoZIndex(pane, Math.max);
}
return this;
},
bringToBack: function () {
var pane = this._map._panes.tilePane;
if (this._container) {
pane.insertBefore(this._container, pane.firstChild);
this._setAutoZIndex(pane, Math.min);
}
return this;
},
@ -1970,6 +1988,13 @@ L.TileLayer = L.Class.extend({
return this;
},
setZIndex: function (zIndex) {
this.options.zIndex = zIndex;
this._updateZIndex();
return this;
},
setUrl: function (url, noRedraw) {
this._url = url;
@ -1989,6 +2014,32 @@ L.TileLayer = L.Class.extend({
return this;
},
_updateZIndex: function () {
if (this._container && this.options.zIndex !== undefined) {
this._container.style.zIndex = this.options.zIndex;
}
},
_setAutoZIndex: function (pane, compare) {
var layers = pane.getElementsByClassName('leaflet-layer'),
edgeZIndex = -compare(Infinity, -Infinity), // -Ifinity for max, Infinity for min
zIndex;
for (var i = 0, len = layers.length; i < len; i++) {
if (layers[i] !== this._container) {
zIndex = parseInt(layers[i].style.zIndex, 10);
if (!isNaN(zIndex)) {
edgeZIndex = compare(edgeZIndex, zIndex);
}
}
}
this._container.style.zIndex = isFinite(edgeZIndex) ? edgeZIndex + compare(1, -1) : '';
},
_updateOpacity: function () {
L.DomUtil.setOpacity(this._container, this.options.opacity);
@ -2006,17 +2057,14 @@ L.TileLayer = L.Class.extend({
},
_initContainer: function () {
var tilePane = this._map._panes.tilePane,
first = tilePane.firstChild;
var tilePane = this._map._panes.tilePane;
if (!this._container || tilePane.empty) {
this._container = L.DomUtil.create('div', 'leaflet-layer');
if (this._insertAtTheBottom && first) {
tilePane.insertBefore(this._container, first);
} else {
this._updateZIndex();
tilePane.appendChild(this._container);
}
if (this.options.opacity < 1) {
this._updateOpacity();
@ -2365,12 +2413,12 @@ L.TileLayer.WMS = L.TileLayer.extend({
L.Util.setOptions(this, options);
},
onAdd: function (map, insertAtTheBottom) {
onAdd: function (map) {
var projectionKey = parseFloat(this.wmsParams.version) >= 1.3 ? 'crs' : 'srs';
this.wmsParams[projectionKey] = map.options.crs.code;
L.TileLayer.prototype.onAdd.call(this, map, insertAtTheBottom);
L.TileLayer.prototype.onAdd.call(this, map);
},
getTileUrl: function (tilePoint, zoom) { // (Point, Number) -> String
@ -2408,6 +2456,7 @@ L.tileLayer.wms = function (url, options) {
return new L.TileLayer(url, options);
};
L.TileLayer.Canvas = L.TileLayer.extend({
options: {
async: false
@ -6341,7 +6390,9 @@ L.Control.Zoom = L.Control.extend({
L.DomEvent
.on(link, 'click', L.DomEvent.stopPropagation)
.on(link, 'click', L.DomEvent.preventDefault)
.on(link, 'click', fn, context);
.on(link, 'click', fn, context)
.on(link, 'dblclick', L.DomEvent.stopPropagation)
.on(link, 'dblclick', L.DomEvent.preventDefault);
return link;
}
@ -6578,13 +6629,15 @@ L.control.scale = function (options) {
L.Control.Layers = L.Control.extend({
options: {
collapsed: true,
position: 'topright'
position: 'topright',
autoZIndex: true
},
initialize: function (baseLayers, overlays, options) {
L.Util.setOptions(this, options);
this._layers = {};
this._lastZIndex = 0;
for (var i in baseLayers) {
if (baseLayers.hasOwnProperty(i)) {
@ -6671,11 +6724,17 @@ L.Control.Layers = L.Control.extend({
_addLayer: function (layer, name, overlay) {
var id = L.Util.stamp(layer);
this._layers[id] = {
layer: layer,
name: name,
overlay: overlay
};
if (this.options.autoZIndex) {
this._lastZIndex++;
layer.setZIndex(this._lastZIndex);
}
},
_update: function () {
@ -7079,7 +7138,7 @@ L.Map.include(!(L.Transition && L.Transition.implemented()) ? {} : {
_panByIfClose: function (center) {
// difference between the new and current centers in pixels
var offset = this._getCenterOffset(center);
var offset = this._getCenterOffset(center)._floor();
if (this._offsetIsWithinView(offset)) {
this.panBy(offset);

2
dist/leaflet.js vendored

File diff suppressed because one or more lines are too long

View File

@ -2,13 +2,15 @@
L.Control.Layers = L.Control.extend({
options: {
collapsed: true,
position: 'topright'
position: 'topright',
autoZIndex: true
},
initialize: function (baseLayers, overlays, options) {
L.Util.setOptions(this, options);
this._layers = {};
this._lastZIndex = 0;
for (var i in baseLayers) {
if (baseLayers.hasOwnProperty(i)) {
@ -95,11 +97,17 @@ L.Control.Layers = L.Control.extend({
_addLayer: function (layer, name, overlay) {
var id = L.Util.stamp(layer);
this._layers[id] = {
layer: layer,
name: name,
overlay: overlay
};
if (this.options.autoZIndex && layer.setZIndex) {
this._lastZIndex++;
layer.setZIndex(this._lastZIndex);
}
},
_update: function () {

View File

@ -34,12 +34,12 @@ L.TileLayer.WMS = L.TileLayer.extend({
L.Util.setOptions(this, options);
},
onAdd: function (map, insertAtTheBottom) {
onAdd: function (map) {
var projectionKey = parseFloat(this.wmsParams.version) >= 1.3 ? 'crs' : 'srs';
this.wmsParams[projectionKey] = map.options.crs.code;
L.TileLayer.prototype.onAdd.call(this, map, insertAtTheBottom);
L.TileLayer.prototype.onAdd.call(this, map);
},
getTileUrl: function (tilePoint, zoom) { // (Point, Number) -> String

View File

@ -12,18 +12,19 @@ L.TileLayer = L.Class.extend({
subdomains: 'abc',
errorTileUrl: '',
attribution: '',
zIndex: 0,
zoomOffset: 0,
opacity: 1,
/* (undefined works too)
zIndex: null,
tms: false,
continuousWorld: false,
noWrap: false,
zoomOffset: 0,
zoomReverse: false,
detectRetina: false,
reuseTiles: false,
*/
unloadInvisibleTiles: L.Browser.mobile,
updateWhenIdle: L.Browser.mobile,
reuseTiles: false
updateWhenIdle: L.Browser.mobile
},
initialize: function (url, options) {
@ -50,9 +51,8 @@ L.TileLayer = L.Class.extend({
}
},
onAdd: function (map, insertAtTheBottom) {
onAdd: function (map) {
this._map = map;
this._insertAtTheBottom = insertAtTheBottom;
// create a container div for tiles
this._initContainer();
@ -97,17 +97,24 @@ L.TileLayer = L.Class.extend({
},
bringToFront: function () {
var pane = this._map._panes.tilePane;
if (this._container) {
this._map._panes.tilePane.appendChild(this._container);
pane.appendChild(this._container);
this._setAutoZIndex(pane, Math.max);
}
return this;
},
bringToBack: function () {
var pane = this._map._panes.tilePane;
if (this._container) {
pane.insertBefore(this._container, pane.firstChild);
this._setAutoZIndex(pane, Math.min);
}
return this;
},
@ -152,11 +159,31 @@ L.TileLayer = L.Class.extend({
},
_updateZIndex: function () {
if (this._container) {
if (this._container && this.options.zIndex !== undefined) {
this._container.style.zIndex = this.options.zIndex;
}
},
_setAutoZIndex: function (pane, compare) {
var layers = pane.getElementsByClassName('leaflet-layer'),
edgeZIndex = -compare(Infinity, -Infinity), // -Ifinity for max, Infinity for min
zIndex;
for (var i = 0, len = layers.length; i < len; i++) {
if (layers[i] !== this._container) {
zIndex = parseInt(layers[i].style.zIndex, 10);
if (!isNaN(zIndex)) {
edgeZIndex = compare(edgeZIndex, zIndex);
}
}
}
this._container.style.zIndex = isFinite(edgeZIndex) ? edgeZIndex + compare(1, -1) : '';
},
_updateOpacity: function () {
L.DomUtil.setOpacity(this._container, this.options.opacity);
@ -174,19 +201,14 @@ L.TileLayer = L.Class.extend({
},
_initContainer: function () {
var tilePane = this._map._panes.tilePane,
first = tilePane.firstChild;
var tilePane = this._map._panes.tilePane;
if (!this._container || tilePane.empty) {
this._container = L.DomUtil.create('div', 'leaflet-layer');
this._updateZIndex();
if (this._insertAtTheBottom && first) {
tilePane.insertBefore(this._container, first);
} else {
tilePane.appendChild(this._container);
}
if (this.options.opacity < 1) {
this._updateOpacity();

View File

@ -138,7 +138,7 @@ L.Map = L.Class.extend({
return this.panBy(new L.Point(dx, dy, true));
},
addLayer: function (layer, insertAtTheBottom) {
addLayer: function (layer) {
// TODO method is too big, refactor
var id = L.Util.stamp(layer);
@ -163,7 +163,7 @@ L.Map = L.Class.extend({
}
var onMapLoad = function () {
layer.onAdd(this, insertAtTheBottom);
layer.onAdd(this);
this.fire('layeradd', {layer: layer});
};