Merge branch 'improve-geojson'
This commit is contained in:
commit
c18c394147
10
CHANGELOG.md
10
CHANGELOG.md
@ -7,8 +7,18 @@ Leaflet Changelog
|
|||||||
|
|
||||||
An in-progress version being developed on the master branch.
|
An in-progress version being developed on the master branch.
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
|
||||||
|
* Improved `GeoJSON` `setStyle` to also accept function (like the corresponding option).
|
||||||
|
* Added `GeoJSON` `resetStyle(layer)`, useful for resetting hover state.
|
||||||
|
* Added `feature` property to layers created with `GeoJSON` (containing the GeoJSON feature data).
|
||||||
|
* Added `FeatureGroup` `bringToFront` and `bringToBack` methods (so that they would work for multipolys).
|
||||||
* Added optional `animate` argument to `Map` `invalidateSize` (by [@ajbeaven](https://github.com/ajbeaven)). [#857](https://github.com/CloudMade/Leaflet/pull/857)
|
* Added optional `animate` argument to `Map` `invalidateSize` (by [@ajbeaven](https://github.com/ajbeaven)). [#857](https://github.com/CloudMade/Leaflet/pull/857)
|
||||||
|
|
||||||
|
### Bugfixes
|
||||||
|
|
||||||
|
* Fixed a bug where `Path` `bringToFront` and `bringToBack` didn't return `this`.
|
||||||
|
|
||||||
## 0.4.2 (August 1, 2012)
|
## 0.4.2 (August 1, 2012)
|
||||||
|
|
||||||
* Fixed a bug where layers control radio buttons would not work correctly in IE7 (by [@danzel](https://github.com/danzel)). [#862](https://github.com/CloudMade/Leaflet/pull/862)
|
* Fixed a bug where layers control radio buttons would not work correctly in IE7 (by [@danzel](https://github.com/danzel)). [#862](https://github.com/CloudMade/Leaflet/pull/862)
|
||||||
|
@ -8,44 +8,155 @@
|
|||||||
|
|
||||||
<link rel="stylesheet" href="../css/screen.css" />
|
<link rel="stylesheet" href="../css/screen.css" />
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#map {
|
||||||
|
width: 800px;
|
||||||
|
height: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
padding: 6px 8px;
|
||||||
|
font: 14px/16px Arial, Helvetica, sans-serif;
|
||||||
|
background: white;
|
||||||
|
background: rgba(255,255,255,0.8);
|
||||||
|
box-shadow: 0 0 15px rgba(0,0,0,0.2);
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
.info h4 {
|
||||||
|
margin: 0 0 5px;
|
||||||
|
color: #777;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend {
|
||||||
|
text-align: left;
|
||||||
|
line-height: 18px;
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
.legend i {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
float: left;
|
||||||
|
margin-right: 8px;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<script src="../leaflet-include.js"></script>
|
<script src="../leaflet-include.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div id="map" style="width: 600px; height: 600px; border: 1px solid #ccc"></div>
|
<div id="map"></div>
|
||||||
<button id="populate">Populate with 10 markers</button>
|
|
||||||
|
|
||||||
<script type="text/javascript" src="geojson-sample.js"></script>
|
<script type="text/javascript" src="us-states.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
var cloudmadeUrl = 'http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png',
|
var map = L.map('map').setView([37.8, -96], 4);
|
||||||
cloudmadeAttribution = 'Map data © 2011 OpenStreetMap contributors, Imagery © 2011 CloudMade',
|
|
||||||
cloudmade = new L.TileLayer(cloudmadeUrl, {maxZoom: 18, attribution: cloudmadeAttribution});
|
|
||||||
|
|
||||||
var map = new L.Map('map', {
|
var cloudmade = L.tileLayer('http://{s}.tile.cloudmade.com/{key}/{styleId}/256/{z}/{x}/{y}.png', {
|
||||||
center: new L.LatLng(0.78, 102.37),
|
attribution: 'Map data © 2011 OpenStreetMap contributors, Imagery © 2011 CloudMade',
|
||||||
zoom: 7,
|
key: 'BC9A493B41014CAABB98F0471D759707',
|
||||||
layers: [cloudmade]
|
styleId: 998
|
||||||
});
|
}).addTo(map);
|
||||||
|
|
||||||
var geojson = L.geoJson(geojsonSample, {
|
|
||||||
|
// control that shows state info on hover
|
||||||
style: function (feature) {
|
var info = L.Util.extend(L.control(), {
|
||||||
return {color: feature.properties.color};
|
|
||||||
|
onAdd: function (map) {
|
||||||
|
this._div = L.DomUtil.create('div', 'info');
|
||||||
|
this.update();
|
||||||
|
return this._div;
|
||||||
},
|
},
|
||||||
|
|
||||||
onEachFeature: function (feature, layer) {
|
update: function (props) {
|
||||||
var popupText = 'geometry type: ' + feature.geometry.type;
|
this._div.innerHTML = '<h4>US Population Density</h4>' + (props ?
|
||||||
|
'<b>' + props.name + '</b><br />' + props.density + ' people / mi<sup>2</sup>'
|
||||||
|
: 'Hover over a state');
|
||||||
|
}
|
||||||
|
|
||||||
if (feature.properties.color) {
|
}).addTo(map);
|
||||||
popupText += '<br/>color: ' + feature.properties.color
|
|
||||||
|
|
||||||
|
// get color depending on population density value
|
||||||
|
function getColor(d) {
|
||||||
|
return d > 1000 ? '#800026' :
|
||||||
|
d > 500 ? '#BD0026' :
|
||||||
|
d > 200 ? '#E31A1C' :
|
||||||
|
d > 100 ? '#FC4E2A' :
|
||||||
|
d > 50 ? '#FD8D3C' :
|
||||||
|
d > 20 ? '#FEB24C' :
|
||||||
|
d > 10 ? '#FED976' :
|
||||||
|
'#FFEDA0';
|
||||||
|
}
|
||||||
|
|
||||||
|
function style(feature) {
|
||||||
|
return {
|
||||||
|
weight: 2,
|
||||||
|
opacity: 1,
|
||||||
|
color: 'white',
|
||||||
|
dashArray: '3',
|
||||||
|
fillOpacity: 0.7,
|
||||||
|
fillColor: getColor(feature.properties.density)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function highlightFeature(e) {
|
||||||
|
var layer = e.target;
|
||||||
|
|
||||||
|
layer.bringToFront().setStyle({
|
||||||
|
weight: 5,
|
||||||
|
color: '#666',
|
||||||
|
dashArray: '',
|
||||||
|
fillOpacity: 0.7
|
||||||
|
});
|
||||||
|
|
||||||
|
info.update(layer.feature.properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
var geojson;
|
||||||
|
|
||||||
|
function resetHighlight(e) {
|
||||||
|
geojson.resetStyle(e.target);
|
||||||
|
info.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
function zoomToFeature(e) {
|
||||||
|
map.fitBounds(e.target.getBounds());
|
||||||
|
}
|
||||||
|
|
||||||
|
function onEachFeature(feature, layer) {
|
||||||
|
layer.on({
|
||||||
|
mouseover: highlightFeature,
|
||||||
|
mouseout: resetHighlight,
|
||||||
|
click: zoomToFeature
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
geojson = L.geoJson(statesData, {
|
||||||
|
style: style,
|
||||||
|
onEachFeature: onEachFeature
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
|
||||||
|
// legend control
|
||||||
|
L.Util.extend(L.control({position: 'bottomright'}), {
|
||||||
|
|
||||||
|
onAdd: function (map) {
|
||||||
|
var div = L.DomUtil.create('div', 'info legend'),
|
||||||
|
grades = [0, 10, 20, 50, 100, 200, 500, 1000],
|
||||||
|
labels = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < grades.length; i++) {
|
||||||
|
labels.push('<i style="background:' + getColor(grades[i] + 1) + '"></i> ' +
|
||||||
|
grades[i] + (grades[i + 1] ? '–' + grades[i + 1] : '+'));
|
||||||
}
|
}
|
||||||
|
|
||||||
layer.bindPopup(popupText);
|
div.innerHTML = labels.join('<br>');
|
||||||
|
return div;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
map.addLayer(geojson);
|
}).addTo(map);
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
54
debug/vector/us-states.js
Normal file
54
debug/vector/us-states.js
Normal file
File diff suppressed because one or more lines are too long
@ -42,6 +42,14 @@ L.FeatureGroup = L.LayerGroup.extend({
|
|||||||
return this.invoke('setStyle', style);
|
return this.invoke('setStyle', style);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
bringToFront: function () {
|
||||||
|
return this.invoke('bringToFront');
|
||||||
|
},
|
||||||
|
|
||||||
|
bringToBack: function () {
|
||||||
|
return this.invoke('bringToBack');
|
||||||
|
},
|
||||||
|
|
||||||
getBounds: function () {
|
getBounds: function () {
|
||||||
var bounds = new L.LatLngBounds();
|
var bounds = new L.LatLngBounds();
|
||||||
this.eachLayer(function (layer) {
|
this.eachLayer(function (layer) {
|
||||||
|
@ -20,27 +20,42 @@ L.GeoJSON = L.FeatureGroup.extend({
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
var options = this.options,
|
var options = this.options;
|
||||||
style = options.style;
|
|
||||||
|
|
||||||
if (options.filter && !options.filter(geojson)) { return; }
|
if (options.filter && !options.filter(geojson)) { return; }
|
||||||
|
|
||||||
var layer = L.GeoJSON.geometryToLayer(geojson, options.pointToLayer);
|
var layer = L.GeoJSON.geometryToLayer(geojson, options.pointToLayer);
|
||||||
|
layer.feature = geojson;
|
||||||
|
|
||||||
if (style) {
|
this.resetStyle(layer);
|
||||||
if (typeof style === 'function') {
|
|
||||||
style = style(geojson);
|
|
||||||
}
|
|
||||||
if (layer.setStyle) {
|
|
||||||
layer.setStyle(style);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.onEachFeature) {
|
if (options.onEachFeature) {
|
||||||
options.onEachFeature(geojson, layer);
|
options.onEachFeature(geojson, layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.addLayer(layer);
|
return this.addLayer(layer);
|
||||||
|
},
|
||||||
|
|
||||||
|
resetStyle: function (layer) {
|
||||||
|
var style = this.options.style;
|
||||||
|
if (style) {
|
||||||
|
this._setLayerStyle(layer, style);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setStyle: function (style) {
|
||||||
|
this.eachLayer(function (layer) {
|
||||||
|
this._setLayerStyle(layer, style);
|
||||||
|
}, this);
|
||||||
|
},
|
||||||
|
|
||||||
|
_setLayerStyle: function (layer, style) {
|
||||||
|
if (typeof style === 'function') {
|
||||||
|
style = style(layer.feature);
|
||||||
|
}
|
||||||
|
if (layer.setStyle) {
|
||||||
|
layer.setStyle(style);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -118,4 +133,4 @@ L.Util.extend(L.GeoJSON, {
|
|||||||
|
|
||||||
L.geoJson = function (geojson, options) {
|
L.geoJson = function (geojson, options) {
|
||||||
return new L.GeoJSON(geojson, options);
|
return new L.GeoJSON(geojson, options);
|
||||||
};
|
};
|
||||||
|
@ -11,6 +11,7 @@ L.Path = L.Path.extend({
|
|||||||
if (this._container) {
|
if (this._container) {
|
||||||
this._map._pathRoot.appendChild(this._container);
|
this._map._pathRoot.appendChild(this._container);
|
||||||
}
|
}
|
||||||
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
bringToBack: function () {
|
bringToBack: function () {
|
||||||
@ -18,6 +19,7 @@ L.Path = L.Path.extend({
|
|||||||
var root = this._map._pathRoot;
|
var root = this._map._pathRoot;
|
||||||
root.insertBefore(this._container, root.firstChild);
|
root.insertBefore(this._container, root.firstChild);
|
||||||
}
|
}
|
||||||
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
getPathString: function () {
|
getPathString: function () {
|
||||||
|
@ -2,11 +2,16 @@ L.Map.mergeOptions({
|
|||||||
zoomAnimation: L.DomUtil.TRANSITION && !L.Browser.android23 && !L.Browser.mobileOpera
|
zoomAnimation: L.DomUtil.TRANSITION && !L.Browser.android23 && !L.Browser.mobileOpera
|
||||||
});
|
});
|
||||||
|
|
||||||
|
L.Map.addInitHook(function () {
|
||||||
|
L.DomEvent.on(this._mapPane, L.Transition.END, this._catchTransitionEnd, this);
|
||||||
|
});
|
||||||
|
|
||||||
L.Map.include(!L.DomUtil.TRANSITION ? {} : {
|
L.Map.include(!L.DomUtil.TRANSITION ? {} : {
|
||||||
|
|
||||||
_zoomToIfClose: function (center, zoom) {
|
_zoomToIfClose: function (center, zoom) {
|
||||||
|
|
||||||
if (this._animatingZoom) { return true; }
|
if (this._animatingZoom) { return true; }
|
||||||
|
|
||||||
if (!this.options.zoomAnimation) { return false; }
|
if (!this.options.zoomAnimation) { return false; }
|
||||||
|
|
||||||
var scale = this.getZoomScale(zoom),
|
var scale = this.getZoomScale(zoom),
|
||||||
@ -21,7 +26,7 @@ L.Map.include(!L.DomUtil.TRANSITION ? {} : {
|
|||||||
.fire('movestart')
|
.fire('movestart')
|
||||||
.fire('zoomstart');
|
.fire('zoomstart');
|
||||||
|
|
||||||
this._prepareTileBg();
|
this._animatingZoom = true;
|
||||||
|
|
||||||
this.fire('zoomanim', {
|
this.fire('zoomanim', {
|
||||||
center: center,
|
center: center,
|
||||||
@ -30,15 +35,19 @@ L.Map.include(!L.DomUtil.TRANSITION ? {} : {
|
|||||||
|
|
||||||
var origin = this._getCenterLayerPoint().add(offset);
|
var origin = this._getCenterLayerPoint().add(offset);
|
||||||
|
|
||||||
|
this._prepareTileBg();
|
||||||
this._runAnimation(center, zoom, scale, origin);
|
this._runAnimation(center, zoom, scale, origin);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_catchTransitionEnd: function (e) {
|
||||||
|
if (this._animatingZoom) {
|
||||||
|
this._onZoomTransitionEnd();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
_runAnimation: function (center, zoom, scale, origin, backwardsTransform) {
|
_runAnimation: function (center, zoom, scale, origin, backwardsTransform) {
|
||||||
this._animatingZoom = true;
|
|
||||||
|
|
||||||
this._animateToCenter = center;
|
this._animateToCenter = center;
|
||||||
this._animateToZoom = zoom;
|
this._animateToZoom = zoom;
|
||||||
|
|
||||||
@ -52,29 +61,14 @@ L.Map.include(!L.DomUtil.TRANSITION ? {} : {
|
|||||||
tileBg.style[transform] += ' translate(0,0)';
|
tileBg.style[transform] += ' translate(0,0)';
|
||||||
}
|
}
|
||||||
|
|
||||||
var scaleStr;
|
|
||||||
|
|
||||||
// Android 2.* doesn't like translate/scale chains, transformOrigin + scale works better but
|
|
||||||
// it breaks touch zoom which Anroid doesn't support anyway, so that's a really ugly hack
|
|
||||||
|
|
||||||
// TODO work around this prettier
|
|
||||||
if (L.Browser.android23) {
|
|
||||||
tileBg.style[transform + 'Origin'] = origin.x + 'px ' + origin.y + 'px';
|
|
||||||
scaleStr = 'scale(' + scale + ')';
|
|
||||||
} else {
|
|
||||||
scaleStr = L.DomUtil.getScaleString(scale, origin);
|
|
||||||
}
|
|
||||||
|
|
||||||
L.Util.falseFn(tileBg.offsetWidth); //hack to make sure transform is updated before running animation
|
L.Util.falseFn(tileBg.offsetWidth); //hack to make sure transform is updated before running animation
|
||||||
|
|
||||||
var options = {};
|
var scaleStr = L.DomUtil.getScaleString(scale, origin),
|
||||||
if (backwardsTransform) {
|
oldTransform = tileBg.style[transform];
|
||||||
options[transform] = tileBg.style[transform] + ' ' + scaleStr;
|
|
||||||
} else {
|
|
||||||
options[transform] = scaleStr + ' ' + tileBg.style[transform];
|
|
||||||
}
|
|
||||||
|
|
||||||
tileBg.transition.run(options);
|
tileBg.style[transform] = backwardsTransform ?
|
||||||
|
oldTransform + ' ' + scaleStr :
|
||||||
|
scaleStr + ' ' + oldTransform;
|
||||||
},
|
},
|
||||||
|
|
||||||
_prepareTileBg: function () {
|
_prepareTileBg: function () {
|
||||||
@ -82,8 +76,7 @@ L.Map.include(!L.DomUtil.TRANSITION ? {} : {
|
|||||||
tileBg = this._tileBg;
|
tileBg = this._tileBg;
|
||||||
|
|
||||||
// If foreground layer doesn't have many tiles but bg layer does, keep the existing bg layer and just zoom it some more
|
// If foreground layer doesn't have many tiles but bg layer does, keep the existing bg layer and just zoom it some more
|
||||||
// (disable this for Android due to it not supporting double translate)
|
if (tileBg &&
|
||||||
if (!L.Browser.android23 && tileBg &&
|
|
||||||
this._getLoadedTilesPercentage(tileBg) > 0.5 &&
|
this._getLoadedTilesPercentage(tileBg) > 0.5 &&
|
||||||
this._getLoadedTilesPercentage(tilePane) < 0.5) {
|
this._getLoadedTilesPercentage(tilePane) < 0.5) {
|
||||||
|
|
||||||
@ -110,14 +103,7 @@ L.Map.include(!L.DomUtil.TRANSITION ? {} : {
|
|||||||
this._tilePane = this._panes.tilePane = tileBg;
|
this._tilePane = this._panes.tilePane = tileBg;
|
||||||
var newTileBg = this._tileBg = tilePane;
|
var newTileBg = this._tileBg = tilePane;
|
||||||
|
|
||||||
if (!newTileBg.transition) {
|
L.DomUtil.addClass(newTileBg, 'leaflet-zoom-animated');
|
||||||
// TODO move to Map options
|
|
||||||
newTileBg.transition = new L.Transition(newTileBg, {
|
|
||||||
duration: 0.25,
|
|
||||||
easing: 'cubic-bezier(0.25,0.1,0.25,0.75)'
|
|
||||||
});
|
|
||||||
newTileBg.transition.on('end', this._onZoomTransitionEnd, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._stopLoadingImages(newTileBg);
|
this._stopLoadingImages(newTileBg);
|
||||||
},
|
},
|
||||||
@ -154,7 +140,6 @@ L.Map.include(!L.DomUtil.TRANSITION ? {} : {
|
|||||||
|
|
||||||
_onZoomTransitionEnd: function () {
|
_onZoomTransitionEnd: function () {
|
||||||
this._restoreTileFront();
|
this._restoreTileFront();
|
||||||
|
|
||||||
L.Util.falseFn(this._tileBg.offsetWidth); // force reflow
|
L.Util.falseFn(this._tileBg.offsetWidth); // force reflow
|
||||||
this._resetView(this._animateToCenter, this._animateToZoom, true, true);
|
this._resetView(this._animateToCenter, this._animateToZoom, true, true);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user