UNPKG

terriajs

Version:

Geospatial data visualization platform.

179 lines 8.05 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import i18next from "i18next"; import { action, observable, runInAction, makeObservable } from "mobx"; import { createRef } from "react"; import CesiumCartographic from "terriajs-cesium/Source/Core/Cartographic"; import URI from "urijs"; import createGuid from "terriajs-cesium/Source/Core/createGuid"; import Rectangle from "terriajs-cesium/Source/Core/Rectangle"; import isDefined from "../../../../Core/isDefined"; import TerriaError from "../../../../Core/TerriaError"; import GeoJsonCatalogItem from "../../../../Models/Catalog/CatalogItems/GeoJsonCatalogItem"; import CommonStrata from "../../../../Models/Definition/CommonStrata"; import createStratumInstance from "../../../../Models/Definition/createStratumInstance"; import { GLYPHS } from "../../../../Styled/Icon"; import StyleTraits from "../../../../Traits/TraitsClasses/StyleTraits"; import MapNavigationItemController from "../../../../ViewModels/MapNavigation/MapNavigationItemController"; export class MyLocation extends MapNavigationItemController { static id = "my-location"; static displayName = "MyLocation"; terria; itemRef = createRef(); _marker; watchId; flown; constructor(props) { super(); makeObservable(this); this.terria = props.terria; this._marker = new GeoJsonCatalogItem(createGuid(), props.terria); this.zoomToMyLocation = this.zoomToMyLocation.bind(this); this.handleLocationError = this.handleLocationError.bind(this); this.augmentedVirtualityEnabled = this.augmentedVirtualityEnabled.bind(this); this.followMeEnabled = this.followMeEnabled.bind(this); } get glyph() { return GLYPHS.geolocationThick; } get viewerMode() { return undefined; } getLocation() { const t = i18next.t.bind(i18next); if (navigator.geolocation) { const options = { enableHighAccuracy: true, timeout: 5000, maximumAge: 0 }; if (!this.augmentedVirtualityEnabled()) { // When Augmented Virtuality is not enabled then just get a single position update. navigator.geolocation.getCurrentPosition(this.zoomToMyLocation, this.handleLocationError, options); } else { // When Augmented Virtuality is enabled then we effectively toggle into watch mode and the position is repeatedly updated. this.watchId = navigator.geolocation.watchPosition(this.zoomToMyLocation, this.handleLocationError, options); } } else { this.terria.raiseErrorToUser(new TerriaError({ sender: this, title: t("location.errorGettingLocation"), message: t("location.browserCannotProvide") })); } } zoomToMyLocation(position) { const t = i18next.t.bind(i18next); const longitude = position.coords.longitude; const latitude = position.coords.latitude; if (this.augmentedVirtualityEnabled()) { // Note: Specifying the value of 27500m here enables this function to approximately mimic the behaviour of // the else case from the cameras initial view and when the viewer pan/zooms out to much. // We use the flag variable flown so that the user is flown to the current location when this function is // first fired, but subsequently the updates are jump location moves, since we assume that the movements are // small and flyTo performs badly when the increments are small (slow and unresponsive). this.terria.augmentedVirtuality.moveTo(CesiumCartographic.fromDegrees(longitude, latitude), 27500, !isDefined(this.flown)); this.flown = true; } else { // west, south, east, north, result const rectangle = Rectangle.fromDegrees(longitude - 0.1, latitude - 0.1, longitude + 0.1, latitude + 0.1); this.terria.currentViewer.zoomTo(rectangle); } runInAction(() => { const name = t("location.myLocation"); this._marker.setTrait(CommonStrata.user, "name", name); this._marker.setTrait(CommonStrata.user, "geoJsonData", { type: "Feature", geometry: { type: "Point", coordinates: [longitude, latitude] }, properties: { title: t("location.location"), longitude: longitude, latitude: latitude } }); // Need to specify rectangle for ideal zoom to work properly in 3D map. const closeUpRange = 0.002; this._marker.setTrait(CommonStrata.user, "rectangle", new Rectangle(longitude - closeUpRange, latitude - closeUpRange, longitude + closeUpRange, latitude + closeUpRange)); this._marker.setTrait(CommonStrata.user, "style", createStratumInstance(StyleTraits, { "marker-size": "25", "marker-color": "#08ABD5", stroke: "#ffffff", "stroke-width": 3 })); this._marker.setTrait(CommonStrata.user, "disableDepthTest", true); this.terria.workbench.add(this._marker); }); } handleLocationError(err) { const t = i18next.t.bind(i18next); let message = err.message; if (message && message.indexOf("Only secure origins are allowed") === 0) { // This is actually the recommended way to check for this error. // https://developers.google.com/web/updates/2016/04/geolocation-on-secure-contexts-only const uri = new URI(window.location); const secureUrl = uri.protocol("https").toString(); message = t("location.originError", { secureUrl: secureUrl }); } else if (err.code === err.PERMISSION_DENIED) { message = t("location.permissionDenied"); } else if (err.code === err.POSITION_UNAVAILABLE) { message = t("location.positionUnavailable"); } else if (err.code === err.TIMEOUT) { message = t("location.timeout"); } this.terria.raiseErrorToUser(new TerriaError({ sender: this, title: t("location.errorGettingLocation"), message: message, showDetails: false })); } augmentedVirtualityEnabled() { return (isDefined(this.terria.augmentedVirtuality) && this.terria.augmentedVirtuality.enabled); } followMeEnabled() { return !!isDefined(this.watchId); } disableFollowMe() { if (isDefined(this.watchId)) { navigator.geolocation.clearWatch(this.watchId); this.watchId = undefined; this.flown = undefined; } } handleClick() { if (this.followMeEnabled()) { this.disableFollowMe(); } else { this.getLocation(); } } } __decorate([ observable ], MyLocation.prototype, "watchId", void 0); __decorate([ observable ], MyLocation.prototype, "flown", void 0); __decorate([ action.bound ], MyLocation.prototype, "getLocation", null); __decorate([ action.bound ], MyLocation.prototype, "disableFollowMe", null); //# sourceMappingURL=MyLocation.js.map