Improved map locate method, added watching and more options

This commit is contained in:
mourner 2011-10-05 16:02:10 +03:00
parent b078e0236e
commit a154f08415
2 changed files with 41 additions and 23 deletions

View File

@ -22,6 +22,7 @@ Leaflet Changelog
#### API improvements #### API improvements
* Improved `LatLng` constructor to be more tolerant (and throw descriptive error if latitude or longitude can't be interpreted as a number). [#136](https://github.com/CloudMade/Leaflet/issues/136) * Improved `LatLng` constructor to be more tolerant (and throw descriptive error if latitude or longitude can't be interpreted as a number). [#136](https://github.com/CloudMade/Leaflet/issues/136)
* Improved `map` `locate` method, added ability to watch location continuously and more options. [#212](https://github.com/CloudMade/Leaflet/issues/212)
* Added ability to add a tile layer below all others (`map.addLayer(layer, true)`) (useful for switching base tile layers). * Added ability to add a tile layer below all others (`map.addLayer(layer, true)`) (useful for switching base tile layers).
* Added `hasLayer` method to `Map`. * Added `hasLayer` method to `Map`.
* Added `TileLayer` `continuousWorld` option to disable tile coordinates checking/wrapping. * Added `TileLayer` `continuousWorld` option to disable tile coordinates checking/wrapping.

View File

@ -3,39 +3,56 @@
*/ */
L.Map.include({ L.Map.include({
locate: function(/*Object*/ options) { locate: function(/*Object*/ options) {
// W3C Geolocation API Spec position options, http://dev.w3.org/geo/api/spec-source.html#position-options
var opts = {timeout: 10000}; this._locationOptions = options = L.Util.extend({
L.Util.extend(opts, options); watch: false,
setView: false,
maxZoom: Infinity,
timeout: 10000,
maximumAge: 0,
enableHighAccuracy: false
}, options);
if (navigator.geolocation) { if (!navigator.geolocation) {
navigator.geolocation.getCurrentPosition( return this.fire('locationerror', {
L.Util.bind(this._handleGeolocationResponse, this),
L.Util.bind(this._handleGeolocationError, this),
opts);
} else {
this.fire('locationerror', {
code: 0, code: 0,
message: "Geolocation not supported." message: "Geolocation not supported."
}); });
} }
var onResponse = L.Util.bind(this._handleGeolocationResponse, this),
onError = L.Util.bind(this._handleGeolocationError, this);
if (options.watch) {
this._locationWatchId = navigator.geolocation.watchPosition(onResponse, onError, options);
} else {
navigator.geolocation.getCurrentPosition(onResponse, onError, options);
}
return this; return this;
}, },
stopLocate: function() {
if (navigator.geolocation) {
navigator.geolocation.clearWatch(this._locationWatchId);
}
},
locateAndSetView: function(maxZoom, options) { locateAndSetView: function(maxZoom, options) {
this._setViewOnLocate = true; options = L.Util.extend({
this._maxLocateZoom = maxZoom || Infinity; maxZoom: maxZoom || Infinity,
setView: true
});
return this.locate(options); return this.locate(options);
}, },
_handleGeolocationError: function(error) { _handleGeolocationError: function(error) {
var c = error.code, var c = error.code,
message = (c == 1 ? "permission denied" : message = (c == 1 ? "permission denied" :
(c == 2 ? "position unavailable" : "timeout")); (c == 2 ? "position unavailable" : "timeout"));
if (this._setViewOnLocate) { if (this._locationOptions.setView && !this._loaded) {
this.fitWorld(); this.fitWorld();
this._setViewOnLocate = false;
} }
this.fire('locationerror', { this.fire('locationerror', {
@ -48,20 +65,20 @@ L.Map.include({
var latAccuracy = 180 * pos.coords.accuracy / 4e7, var latAccuracy = 180 * pos.coords.accuracy / 4e7,
lngAccuracy = latAccuracy * 2, lngAccuracy = latAccuracy * 2,
lat = pos.coords.latitude, lat = pos.coords.latitude,
lng = pos.coords.longitude; lng = pos.coords.longitude,
latlng = new L.LatLng(lat, lng);
var sw = new L.LatLng(lat - latAccuracy, lng - lngAccuracy), var sw = new L.LatLng(lat - latAccuracy, lng - lngAccuracy),
ne = new L.LatLng(lat + latAccuracy, lng + lngAccuracy), ne = new L.LatLng(lat + latAccuracy, lng + lngAccuracy),
bounds = new L.LatLngBounds(sw, ne); bounds = new L.LatLngBounds(sw, ne);
if (this._setViewOnLocate) { if (this._locationOptions.setView) {
var zoom = Math.min(this.getBoundsZoom(bounds), this._maxLocateZoom); var zoom = Math.min(this.getBoundsZoom(bounds), this._locationOptions.maxZoom);
this.setView(bounds.getCenter(), zoom); this.setView(latlng, zoom);
this._setViewOnLocate = false;
} }
this.fire('locationfound', { this.fire('locationfound', {
latlng: new L.LatLng(lat, lng), latlng: latlng,
bounds: bounds, bounds: bounds,
accuracy: pos.coords.accuracy accuracy: pos.coords.accuracy
}); });