Last active
February 21, 2022 12:44
-
-
Save sasha7/0c32f3686eb49d44ccc8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {Injectable, provide} from 'angular2/core'; | |
import {Observable} from 'rxjs'; | |
const GEOLOCATION_ERRORS = { | |
'errors.location.unsupportedBrowser': 'Browser does not support location services', | |
'errors.location.permissionDenied': 'You have rejected access to your location', | |
'errors.location.positionUnavailable': 'Unable to determine your location', | |
'errors.location.timeout': 'Service timeout has been reached' | |
}; | |
@Injectable() | |
export class GeolocationService { | |
/** | |
* Obtains the geographic position, in terms of latitude and longitude coordinates, of the device. | |
* @param {Object} [opts] An object literal to specify one or more of the following attributes and desired values: | |
* - enableHighAccuracy: Specify true to obtain the most accurate position possible, or false to optimize in favor of performance and power consumption. | |
* - timeout: An Integer value that indicates the time, in milliseconds, allowed for obtaining the position. | |
* If timeout is Infinity, (the default value) the location request will not time out. | |
* If timeout is zero (0) or negative, the results depend on the behavior of the location provider. | |
* - maximumAge: An Integer value indicating the maximum age, in milliseconds, of cached position information. | |
* If maximumAge is non-zero, and a cached position that is no older than maximumAge is available, the cached position is used instead of obtaining an updated location. | |
* If maximumAge is zero (0), watchPosition always tries to obtain an updated position, even if a cached position is already available. | |
* If maximumAge is Infinity, any cached position is used, regardless of its age, and watchPosition only tries to obtain an updated position if no cached position data exists. | |
* @returns {Observable} An observable sequence with the geographical location of the device running the client. | |
*/ | |
public getLocation(opts): Observable<any> { | |
return Observable.create(observer => { | |
if (window.navigator && window.navigator.geolocation) { | |
window.navigator.geolocation.getCurrentPosition( | |
(position) => { | |
observer.next(position); | |
observer.complete(); | |
}, | |
(error) => { | |
switch (error.code) { | |
case 1: | |
observer.error(GEOLOCATION_ERRORS['errors.location.permissionDenied']); | |
break; | |
case 2: | |
observer.error(GEOLOCATION_ERRORS['errors.location.positionUnavailable']); | |
break; | |
case 3: | |
observer.error(GEOLOCATION_ERRORS['errors.location.timeout']); | |
break; | |
} | |
}, | |
opts); | |
} | |
else { | |
observer.error(GEOLOCATION_ERRORS['errors.location.unsupportedBrowser']); | |
} | |
}); | |
} | |
} | |
export var geolocationServiceInjectables: Array<any> = [ | |
provide(GeolocationService, { useClass: GeolocationService }) | |
]; |
A different but similar approach if anyone is interested - this one is based on publishing events when the service is enabled:
Written with angular 5.
I'm not very strong with observables so the code might be shorter.
import { Injectable, EventEmitter } from "@angular/core";
declare type GeoLocationServiceState = "disabled" | "searching" | "tracking";
@Injectable()
export class GeoLocationService {
private state: GeoLocationServiceState;
private watchNumber: number;
public positionChanged: EventEmitter<Position>;
constructor() {
this.watchNumber = -1;
this.positionChanged = new EventEmitter();
this.state = "disabled";
}
public getState(): GeoLocationServiceState {
return this.state;
}
public enable() {
switch (this.state) {
case "disabled":
this.startWatching();
return;
case "searching":
case "tracking":
return;
}
}
public disable() {
switch (this.state) {
case "disabled":
return;
case "searching":
case "tracking":
this.stopWatching();
return;
}
}
private startWatching() {
if (window.navigator && window.navigator.geolocation) {
this.state = "searching";
this.watchNumber = window.navigator.geolocation.watchPosition(
(position) => {
this.state = "tracking";
this.positionChanged.next(position);
},
(error) => {
// sending error will terminate the stream
this.positionChanged.next(null);
this.disable();
},
{
enableHighAccuracy: true,
timeout: 5000
});
}
}
private stopWatching() {
if (this.watchNumber !== -1) {
window.navigator.geolocation.clearWatch(this.watchNumber);
this.watchNumber = -1;
this.state = "disabled";
}
}
}
Thank you! I use rx-dom library for this. I think it can be more convenient.
Hi @andreypelykh, did you update this with rx-dom? if yes please share.
Hello, @rmxakalogistik! What do you mean? You can simply use an example from the link that I provided. https://github.com/Reactive-Extensions/RxJS-DOM/blob/master/doc/operators/watchposition.md#example
var source = Rx.DOM.geolocation.watchPosition();
var subscription = source.subscribe(
function (pos) {
console.log('Next:' + position.coords.latitude + ',' + position.coords.longitude);
},
function (err) {
var message = '';
switch (err.code) {
case err.PERMISSION_DENIED:
message = 'Permission denied';
break;
case err.POSITION_UNAVAILABLE:
message = 'Position unavailable';
break;
case err.PERMISSION_DENIED_TIMEOUT:
message = 'Position timeout';
break;
}
console.log('Error: ' + message);
},
function () {
console.log('Completed');
});
This library solved the problem and works with Angular 11: https://www.npmjs.com/package/@ng-web-apis/geolocation
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
`
Angular 5 Geolocation service
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
const GEOLOCATION_ERRORS = {
'errors.location.unsupportedBrowser': 'Browser does not support location services',
'errors.location.permissionDenied': 'You have rejected access to your location',
'errors.location.positionUnavailable': 'Unable to determine your location',
'errors.location.timeout': 'Service timeout has been reached'
};
@Injectable()
export class GeoLocationService {
public getLocation(geoLocationOptions?: any): Observable {
geoLocationOptions = geoLocationOptions || { timeout: 5000 };
`