move geolocation methods to Map.js
Vladimir Agafonkin
7 years ago
250 | 250 | ], |
251 | 251 | deps: ['AnimationPan'], |
252 | 252 | desc: 'Smooth zooming animation. Works only on browsers that support CSS3 Transitions.' |
253 | }, | |
254 | ||
255 | Geolocation: { | |
256 | src: ['map/ext/Map.Geolocation.js'], | |
257 | desc: 'Adds Map#locate method and related events to make geolocation easier.', | |
258 | heading: 'Misc' | |
259 | 253 | } |
260 | 254 | }; |
261 | 255 |
378 | 378 | return this._stop(); |
379 | 379 | }, |
380 | 380 | |
381 | // @section Geolocation methods | |
382 | // @method locate(options?: Locate options): this | |
383 | // Tries to locate the user using the Geolocation API, firing a [`locationfound`](#map-locationfound) | |
384 | // event with location data on success or a [`locationerror`](#map-locationerror) event on failure, | |
385 | // and optionally sets the map view to the user's location with respect to | |
386 | // detection accuracy (or to the world view if geolocation failed). | |
387 | // Note that, if your page doesn't use HTTPS, this method will fail in | |
388 | // modern browsers ([Chrome 50 and newer](https://sites.google.com/a/chromium.org/dev/Home/chromium-security/deprecating-powerful-features-on-insecure-origins)) | |
389 | // See `Locate options` for more details. | |
390 | locate: function (options) { | |
391 | ||
392 | options = this._locateOptions = L.extend({ | |
393 | timeout: 10000, | |
394 | watch: false | |
395 | // setView: false | |
396 | // maxZoom: <Number> | |
397 | // maximumAge: 0 | |
398 | // enableHighAccuracy: false | |
399 | }, options); | |
400 | ||
401 | if (!('geolocation' in navigator)) { | |
402 | this._handleGeolocationError({ | |
403 | code: 0, | |
404 | message: 'Geolocation not supported.' | |
405 | }); | |
406 | return this; | |
407 | } | |
408 | ||
409 | var onResponse = L.bind(this._handleGeolocationResponse, this), | |
410 | onError = L.bind(this._handleGeolocationError, this); | |
411 | ||
412 | if (options.watch) { | |
413 | this._locationWatchId = | |
414 | navigator.geolocation.watchPosition(onResponse, onError, options); | |
415 | } else { | |
416 | navigator.geolocation.getCurrentPosition(onResponse, onError, options); | |
417 | } | |
418 | return this; | |
419 | }, | |
420 | ||
421 | // @method stopLocate(): this | |
422 | // Stops watching location previously initiated by `map.locate({watch: true})` | |
423 | // and aborts resetting the map view if map.locate was called with | |
424 | // `{setView: true}`. | |
425 | stopLocate: function () { | |
426 | if (navigator.geolocation && navigator.geolocation.clearWatch) { | |
427 | navigator.geolocation.clearWatch(this._locationWatchId); | |
428 | } | |
429 | if (this._locateOptions) { | |
430 | this._locateOptions.setView = false; | |
431 | } | |
432 | return this; | |
433 | }, | |
434 | ||
435 | _handleGeolocationError: function (error) { | |
436 | var c = error.code, | |
437 | message = error.message || | |
438 | (c === 1 ? 'permission denied' : | |
439 | (c === 2 ? 'position unavailable' : 'timeout')); | |
440 | ||
441 | if (this._locateOptions.setView && !this._loaded) { | |
442 | this.fitWorld(); | |
443 | } | |
444 | ||
445 | // @section Location events | |
446 | // @event locationerror: ErrorEvent | |
447 | // Fired when geolocation (using the [`locate`](#map-locate) method) failed. | |
448 | this.fire('locationerror', { | |
449 | code: c, | |
450 | message: 'Geolocation error: ' + message + '.' | |
451 | }); | |
452 | }, | |
453 | ||
454 | _handleGeolocationResponse: function (pos) { | |
455 | var lat = pos.coords.latitude, | |
456 | lng = pos.coords.longitude, | |
457 | latlng = new L.LatLng(lat, lng), | |
458 | bounds = latlng.toBounds(pos.coords.accuracy), | |
459 | options = this._locateOptions; | |
460 | ||
461 | if (options.setView) { | |
462 | var zoom = this.getBoundsZoom(bounds); | |
463 | this.setView(latlng, options.maxZoom ? Math.min(zoom, options.maxZoom) : zoom); | |
464 | } | |
465 | ||
466 | var data = { | |
467 | latlng: latlng, | |
468 | bounds: bounds, | |
469 | timestamp: pos.timestamp | |
470 | }; | |
471 | ||
472 | for (var i in pos.coords) { | |
473 | if (typeof pos.coords[i] === 'number') { | |
474 | data[i] = pos.coords[i]; | |
475 | } | |
476 | } | |
477 | ||
478 | // @event locationfound: LocationEvent | |
479 | // Fired when geolocation (using the [`locate`](#map-locate) method) | |
480 | // went successfully. | |
481 | this.fire('locationfound', data); | |
482 | }, | |
381 | 483 | |
382 | 484 | // TODO handler.addTo |
383 | 485 | // TODO Appropiate docs section? |
0 | /* | |
1 | * Provides L.Map with convenient shortcuts for using browser geolocation features. | |
2 | */ | |
3 | ||
4 | // @namespace Map | |
5 | ||
6 | L.Map.include({ | |
7 | // @section Geolocation methods | |
8 | _defaultLocateOptions: { | |
9 | timeout: 10000, | |
10 | watch: false | |
11 | // setView: false | |
12 | // maxZoom: <Number> | |
13 | // maximumAge: 0 | |
14 | // enableHighAccuracy: false | |
15 | }, | |
16 | ||
17 | // @method locate(options?: Locate options): this | |
18 | // Tries to locate the user using the Geolocation API, firing a [`locationfound`](#map-locationfound) | |
19 | // event with location data on success or a [`locationerror`](#map-locationerror) event on failure, | |
20 | // and optionally sets the map view to the user's location with respect to | |
21 | // detection accuracy (or to the world view if geolocation failed). | |
22 | // Note that, if your page doesn't use HTTPS, this method will fail in | |
23 | // modern browsers ([Chrome 50 and newer](https://sites.google.com/a/chromium.org/dev/Home/chromium-security/deprecating-powerful-features-on-insecure-origins)) | |
24 | // See `Locate options` for more details. | |
25 | locate: function (options) { | |
26 | ||
27 | options = this._locateOptions = L.extend({}, this._defaultLocateOptions, options); | |
28 | ||
29 | if (!('geolocation' in navigator)) { | |
30 | this._handleGeolocationError({ | |
31 | code: 0, | |
32 | message: 'Geolocation not supported.' | |
33 | }); | |
34 | return this; | |
35 | } | |
36 | ||
37 | var onResponse = L.bind(this._handleGeolocationResponse, this), | |
38 | onError = L.bind(this._handleGeolocationError, this); | |
39 | ||
40 | if (options.watch) { | |
41 | this._locationWatchId = | |
42 | navigator.geolocation.watchPosition(onResponse, onError, options); | |
43 | } else { | |
44 | navigator.geolocation.getCurrentPosition(onResponse, onError, options); | |
45 | } | |
46 | return this; | |
47 | }, | |
48 | ||
49 | // @method stopLocate(): this | |
50 | // Stops watching location previously initiated by `map.locate({watch: true})` | |
51 | // and aborts resetting the map view if map.locate was called with | |
52 | // `{setView: true}`. | |
53 | stopLocate: function () { | |
54 | if (navigator.geolocation && navigator.geolocation.clearWatch) { | |
55 | navigator.geolocation.clearWatch(this._locationWatchId); | |
56 | } | |
57 | if (this._locateOptions) { | |
58 | this._locateOptions.setView = false; | |
59 | } | |
60 | return this; | |
61 | }, | |
62 | ||
63 | _handleGeolocationError: function (error) { | |
64 | var c = error.code, | |
65 | message = error.message || | |
66 | (c === 1 ? 'permission denied' : | |
67 | (c === 2 ? 'position unavailable' : 'timeout')); | |
68 | ||
69 | if (this._locateOptions.setView && !this._loaded) { | |
70 | this.fitWorld(); | |
71 | } | |
72 | ||
73 | // @section Location events | |
74 | // @event locationerror: ErrorEvent | |
75 | // Fired when geolocation (using the [`locate`](#map-locate) method) failed. | |
76 | this.fire('locationerror', { | |
77 | code: c, | |
78 | message: 'Geolocation error: ' + message + '.' | |
79 | }); | |
80 | }, | |
81 | ||
82 | _handleGeolocationResponse: function (pos) { | |
83 | var lat = pos.coords.latitude, | |
84 | lng = pos.coords.longitude, | |
85 | latlng = new L.LatLng(lat, lng), | |
86 | bounds = latlng.toBounds(pos.coords.accuracy), | |
87 | options = this._locateOptions; | |
88 | ||
89 | if (options.setView) { | |
90 | var zoom = this.getBoundsZoom(bounds); | |
91 | this.setView(latlng, options.maxZoom ? Math.min(zoom, options.maxZoom) : zoom); | |
92 | } | |
93 | ||
94 | var data = { | |
95 | latlng: latlng, | |
96 | bounds: bounds, | |
97 | timestamp: pos.timestamp | |
98 | }; | |
99 | ||
100 | for (var i in pos.coords) { | |
101 | if (typeof pos.coords[i] === 'number') { | |
102 | data[i] = pos.coords[i]; | |
103 | } | |
104 | } | |
105 | ||
106 | // @event locationfound: LocationEvent | |
107 | // Fired when geolocation (using the [`locate`](#map-locate) method) | |
108 | // went successfully. | |
109 | this.fire('locationfound', data); | |
110 | } | |
111 | }); |