diff --git a/src/services/map-service.js b/src/services/map-service.js index 5aefb5eada744855a97794e1990b04a83609d493..e936cc9f6318fb5532d5e433ca664b97969c84b9 100644 --- a/src/services/map-service.js +++ b/src/services/map-service.js @@ -2,7 +2,7 @@ import TileWMS from 'ol/source/TileWMS'; import { View, Map } from 'ol'; import { ScaleLine, Zoom, Attribution, FullScreen } from 'ol/control'; import TileLayer from 'ol/layer/Tile'; -import { transform, transformExtent } from 'ol/proj.js'; +import { transform, transformExtent, fromLonLat } from 'ol/proj.js'; import { defaults } from 'ol/interaction'; import XYZ from 'ol/source/XYZ'; import VectorTileLayer from 'ol/layer/VectorTile'; @@ -16,8 +16,10 @@ import { import { asArray } from 'ol/color'; import VectorSource from 'ol/source/Vector'; import VectorLayer from 'ol/layer/Vector'; -import { fromLonLat } from 'ol/proj.js'; import OverlayPositioning from 'ol/OverlayPositioning'; +import Geolocation from 'ol/Geolocation.js'; +import Feature from 'ol/Feature.js'; +import Point from 'ol/geom/Point.js'; import axios from '@/axios-client.js'; import router from '@/router'; @@ -39,6 +41,8 @@ const mapService = { queryParams: {}, + geolocation: undefined, + getMap() { return this.map; @@ -58,6 +62,7 @@ const mapService = { zoom, zoomControl = true, fullScreenControl = false, + geolocationControl = false, interactions = { doubleClickZoom: false, mouseWheelZoom: false, dragPan: true }, controls = [ new Attribution({ collapsible: false }), @@ -92,6 +97,10 @@ const mapService = { if (zoomControl) { this.map.addControl(new Zoom({ zoomInTipLabel: 'Zoomer', zoomOutTipLabel: 'Dézoomer' })); } + if (geolocationControl) { + this.initGeolocation(); + } + this.map.once('rendercomplete', () => { this.map.updateSize(); }); @@ -120,6 +129,66 @@ const mapService = { return this.map; }, + initGeolocation() { + this.geolocation = new Geolocation({ + // enableHighAccuracy must be set to true to have the heading value. + trackingOptions: { + enableHighAccuracy: true, + }, + projection: this.map.getView().getProjection(), + }); + + // handle this.geolocation error. + this.geolocation.on('error', (error) => { + console.error(error.message); + }); + + /* const accuracyFeature = new Feature(); + this.geolocation.on('change:accuracyGeometry', () => { + accuracyFeature.setGeometry(this.geolocation.getAccuracyGeometry()); + }); */ + + const positionFeature = new Feature(); + positionFeature.setStyle( + new Style({ + image: new Circle({ + radius: 6, + fill: new Fill({ + color: '#3399CC', + }), + stroke: new Stroke({ + color: '#fff', + width: 2, + }), + }), + }) + ); + + this.geolocation.on('change:position', () => { + const coordinates = this.geolocation.getPosition(); + positionFeature.setGeometry(coordinates ? new Point(coordinates) : null); + if (coordinates) { + this.map.getView().animate( + { zoom: 16 }, + { center: coordinates }, + { duration: 1000 } + ); + } + }); + + new VectorLayer({ + map: this.map, + source: new VectorSource({ + features: [positionFeature], + //features: [accuracyFeature, positionFeature], + }), + }); + console.log('initGeolocation'); + }, + + toggleGeolocation(value) { + this.geolocation.setTracking(value); + }, addRouterToPopup({ featureId, featureTypeSlug, index }) { diff --git a/src/views/Feature/FeatureEdit.vue b/src/views/Feature/FeatureEdit.vue index b156f07c8c517d5e4be302348d403d5d274c56fd..9e3f4533f10b6d9c56e47215128d4b087c1a9776 100644 --- a/src/views/Feature/FeatureEdit.vue +++ b/src/views/Feature/FeatureEdit.vue @@ -15,8 +15,6 @@ <form id="form-feature-edit" - action="" - method="post" enctype="multipart/form-data" class="ui form" > @@ -252,6 +250,16 @@ ref="map" > <SidebarLayers v-if="basemaps && map" /> + + <div class="geolocation-container"> + <button + class="button-geolocation" + @click.prevent="toggleTracking" + > + <i class="crosshairs icon" /> + </button> + </div> + <Geocoder /> <EditingToolbar v-if="isEditable" @@ -445,6 +453,7 @@ export default { value: null, }, }, + tracking: false, }; }, @@ -667,6 +676,11 @@ export default { this.showGeoRef = !this.showGeoRef; }, + toggleTracking() { + this.tracking = !this.tracking; + mapService.toggleGeolocation(this.tracking); + }, + handleFileUpload() { this.erreurUploadMessage = ''; this.file = this.$refs.file.files[0]; @@ -970,7 +984,8 @@ export default { mapDefaultViewZoom, maxZoom: this.project.map_max_zoom_level, interactions : { doubleClickZoom :false, mouseWheelZoom:true, dragPan:true }, - fullScreenControl: true + fullScreenControl: true, + geolocationControl: true, }); const currentFeatureId = this.$route.params.slug_signal; const url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}v2/features/?feature_type__slug=${this.$route.params.slug_type_signal}&project__slug=${this.$route.params.slug}&output=geojson`; @@ -1035,6 +1050,35 @@ export default { width: 100%; border: 1px solid grey; } + + +div.geolocation-container { + position: absolute; + right: 0.5em; + /* each button have .5em space between, zoom buttons are 60px high and full screen button is 34px high */ + top: calc(1.5em + 60px + 34px + 100px); + z-index: 1000; + border: 2px solid rgba(0,0,0,.2); + background-clip: padding-box; + padding: 0; + border-radius: 2px; + display: flex; +} +button.button-geolocation { + border: none; + padding: 0; + margin: 0; + text-align: center; + background-color: #fff; + color: rgb(39, 39, 39); + width: 28px; + height: 28px; + font: 700 18px Lucida Console,Monaco,monospace; + border-radius: 2px; + line-height: 1.15; + cursor: pointer; +} + #get-geom-from-image-file { margin-bottom: 5px; }