import * as AFRAME from "aframe"; AFRAME.registerComponent("gps-entity-place", { _cameraGps: null, schema: { longitude: { type: "number", default: 0, }, latitude: { type: "number", default: 0, }, }, remove: function () { // cleaning listeners when the entity is removed from the DOM window.removeEventListener( "gps-camera-origin-coord-set", this.coordSetListener ); window.removeEventListener( "gps-camera-update-position", this.updatePositionListener ); }, init: function () { this.coordSetListener = () => { if (!this._cameraGps) { var camera = document.querySelector("[gps-camera]"); if (!camera.components["gps-camera"]) { console.error("gps-camera not initialized"); return; } this._cameraGps = camera.components["gps-camera"]; } this._updatePosition(); }; this.updatePositionListener = (ev) => { if (!this.data || !this._cameraGps) { return; } var dstCoords = { longitude: this.data.longitude, latitude: this.data.latitude, }; // it's actually a 'distance place', but we don't call it with last param, because we want to retrieve distance even if it's < minDistance property var distanceForMsg = this._cameraGps.computeDistanceMeters( ev.detail.position, dstCoords ); this.el.setAttribute("distance", distanceForMsg); this.el.setAttribute("distanceMsg", this._formatDistance(distanceForMsg)); this.el.dispatchEvent( new CustomEvent("gps-entity-place-update-position", { detail: { distance: distanceForMsg }, }) ); var actualDistance = this._cameraGps.computeDistanceMeters( ev.detail.position, dstCoords, true ); if (actualDistance === Number.MAX_SAFE_INTEGER) { this.hideForMinDistance(this.el, true); } else { this.hideForMinDistance(this.el, false); } }; window.addEventListener( "gps-camera-origin-coord-set", this.coordSetListener ); window.addEventListener( "gps-camera-update-position", this.updatePositionListener ); this._positionXDebug = 0; window.dispatchEvent( new CustomEvent("gps-entity-place-added", { detail: { component: this.el }, }) ); }, /** * Hide entity according to minDistance property * @returns {void} */ hideForMinDistance: function (el, hideEntity) { if (hideEntity) { el.setAttribute("visible", "false"); } else { el.setAttribute("visible", "true"); } }, /** * Update place position * @returns {void} */ _updatePosition: function () { var position = { x: 0, y: this.el.getAttribute("position").y || 0, z: 0 }; // update position.x var dstCoords = { longitude: this.data.longitude, latitude: this._cameraGps.originCoords.latitude, }; position.x = this._cameraGps.computeDistanceMeters( this._cameraGps.originCoords, dstCoords ); this._positionXDebug = position.x; position.x *= this.data.longitude > this._cameraGps.originCoords.longitude ? 1 : -1; // update position.z var dstCoords = { longitude: this._cameraGps.originCoords.longitude, latitude: this.data.latitude, }; position.z = this._cameraGps.computeDistanceMeters( this._cameraGps.originCoords, dstCoords ); position.z *= this.data.latitude > this._cameraGps.originCoords.latitude ? -1 : 1; if (position.y !== 0) { var altitude = this._cameraGps.originCoords.altitude !== undefined ? this._cameraGps.originCoords.altitude : 0; position.y = position.y - altitude; } // update element's position in 3D world this.el.setAttribute("position", position); }, /** * Format distances string * * @param {String} distance */ _formatDistance: function (distance) { distance = distance.toFixed(0); if (distance >= 1000) { return distance / 1000 + " kilometers"; } return distance + " meters"; }, });