commit 7ae72a8901dc9ecb001359e4b005684291472605
parent 257d6c51c332e12b4f3d61319c1855424432d092
Author: Sergej Orlov <wladimirych@gmail.com>
Date: Wed, 25 Apr 2018 10:47:20 +0300
add geolocation control #59
Diffstat:
6 files changed, 191 insertions(+), 1 deletion(-)
diff --git a/package.json b/package.json
@@ -61,6 +61,7 @@
"image-promise": "^4.0.1",
"knockout": "^3.4.0",
"leaflet": "1.0.3",
+ "leaflet.locatecontrol": "^0.62.0",
"load-script": "^1.0.0",
"mapillary-js": "2.5.2",
"pbf": "^3.0.5",
diff --git a/src/App.js b/src/App.js
@@ -26,6 +26,8 @@ import 'lib/leaflet.control.jnx';
import 'lib/leaflet.control.jnx/hash-state';
import 'lib/leaflet.control.azimuth';
import {hashState, bindHashStateReadOnly} from 'lib/leaflet.hashState/hashState';
+import {MyLocate} from 'lib/leaflet.control.mylocation';
+
function setUp() {
fixAll();
@@ -61,11 +63,13 @@ function setUp() {
.enableHashState('n2');
L.Control.Panoramas.hashStateUpgrader(panoramas).enableHashState('n');
-
new L.Control.Coordinates({position: 'topleft'}).addTo(map);
const azimuthControl = new L.Control.Azimuth({position: 'topleft'}).addTo(map);
+ const location = new MyLocate();
+ location.addTo(map);
+
/////////// controls top-right corner
const layersControl = L.control.layers(null, null, {collapsed: false})
diff --git a/src/lib/leaflet.control.mylocation/index.js b/src/lib/leaflet.control.mylocation/index.js
@@ -0,0 +1,137 @@
+import L from 'leaflet';
+import 'leaflet.locatecontrol';
+import './style.css';
+
+
+const MyLocate = L.Control.Locate.extend({
+ options: {
+ icon: 'icon-position',
+ iconLoading: 'icon-position',
+ setView: 'untilPan',
+ flyTo: true,
+ cacheLocation: false,
+ showPopup: false,
+ locateOptions: {
+ enableHighAccuracy: true,
+ watch: true,
+ setView: false
+ },
+ maxZoom: 16,
+
+ circleStyle: {
+ interactive: false,
+ color: '#4271a8',
+ fillOpacity: 0.3,
+ weight: 0,
+ },
+ markerStyle: {
+ color: '#2a85d4',
+ weight: 2.5,
+ opacity: 0.8,
+ fillOpacity: 0.4,
+ radius: 8
+ },
+ minCirclePixelRadius: 50
+
+ },
+
+ start: function() {
+ this.options.keepCurrentZoomLevel = false;
+ L.Control.Locate.prototype.start.call(this);
+ },
+
+ _onDrag: function() {
+ if (this._settingView) {
+ return;
+ }
+ L.Control.Locate.prototype._onDrag.call(this);
+ },
+
+ _activate: function() {
+ if (!this._active) {
+ this._map.on('movestart', this._onDrag, this);
+ this._map.on('zoom', this._onZoom, this);
+ }
+ L.Control.Locate.prototype._activate.call(this);
+ },
+
+ _deactivate: function() {
+ L.Control.Locate.prototype._deactivate.call(this);
+ this._map.off('movestart', this._onDrag, this);
+ this._map.off('zoom', this._onZoom, this);
+ },
+
+ _onZoom: function() {
+ if (!this._circle || !this.options.minCirclePixelRadius) {
+ return;
+ }
+ if (typeof this._circle._origFillOpacity === 'undefined') {
+ this._circle._origFillOpacity = this._circle.options.fillOpacity;
+ }
+ L.Util.requestAnimFrame(() => {
+ const opacity = this._circle._radius < this.options.minCirclePixelRadius ?
+ 0 : this._circle._origFillOpacity;
+ console.log(this._circle._radius, this.options.minCirclePixelRadius, this._circle._origFillOpacity);
+ this._circle.setStyle({fillOpacity: opacity});
+ });
+ },
+
+ _onClick: function() {
+ this.options.keepCurrentZoomLevel = false;
+ L.Control.Locate.prototype._onClick.call(this);
+ },
+
+ _onMarkerClick: function() {
+ this._userPanned = false;
+ this._updateContainerStyle();
+ this.options.keepCurrentZoomLevel = false;
+ this.setView();
+ },
+
+ _drawMarker: function() {
+ var newMarker = !this._marker;
+ L.Control.Locate.prototype._drawMarker.call(this);
+ if (newMarker) {
+ this._marker.on('click', this._onMarkerClick.bind(this));
+ }
+ },
+
+ setView: function() {
+ this._drawMarker();
+ if (this._isOutsideMapBounds()) {
+ this._event = undefined; // clear the current location so we can get back into the bounds
+ this.options.onLocationOutsideMapBounds(this);
+ } else {
+ var coords = this._event,
+ lat = coords.latitude,
+ lng = coords.longitude,
+ latlng = new L.LatLng(lat, lng),
+ zoom;
+ if (!this.options.keepCurrentZoomLevel) {
+ // fix for leaflet issue #6139
+ var bounds = latlng.toBounds(coords.accuracy * 2);
+ zoom = this._map.getBoundsZoom(bounds);
+ zoom = this.options.maxZoom ? Math.min(zoom, this.options.maxZoom) : zoom;
+ }
+ this._settingView = true;
+ this._map.once('moveend', () => {
+ this._settingView = false;
+ });
+ var f = this.options.flyTo ? this._map.flyTo : this._map.setView;
+ f.call(this._map, latlng, zoom);
+
+ this.options.keepCurrentZoomLevel = true;
+ }
+ },
+
+ }
+);
+
+export {MyLocate};
+
+
+// + при включение зумить, но не ближе ~16 уровня и не ближе круга точности.
+// + зум можно уменьшать только если круг точности большой и на 16 уровень не помещается
+// + при обновлении позиции зум не менять
+// + при плавном приближении маркер сильно зумится
+// + а что с сохранением состоямия в localStorage? -- ничего
+\ No newline at end of file
diff --git a/src/lib/leaflet.control.mylocation/location-arrow-active.svg b/src/lib/leaflet.control.mylocation/location-arrow-active.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<svg height="1792" viewBox="0 0 1792 1792" width="1792" xmlns="http://www.w3.org/2000/svg">
+ <path style="fill:#c00;" d="M1593 349l-640 1280q-17 35-57 35-5 0-15-2-22-5-35.5-22.5t-13.5-39.5v-576h-576q-22 0-39.5-13.5t-22.5-35.5 4-42 29-30l1280-640q13-7 29-7 27 0 45 19 15 14 18.5 34.5t-6.5 39.5z"/>
+</svg>
+\ No newline at end of file
diff --git a/src/lib/leaflet.control.mylocation/location-arrow.svg b/src/lib/leaflet.control.mylocation/location-arrow.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<svg height="1792" viewBox="0 0 1792 1792" width="1792" xmlns="http://www.w3.org/2000/svg">
+ <path style="fill:#555;" d="M1593 349l-640 1280q-17 35-57 35-5 0-15-2-22-5-35.5-22.5t-13.5-39.5v-576h-576q-22 0-39.5-13.5t-22.5-35.5 4-42 29-30l1280-640q13-7 29-7 27 0 45 19 15 14 18.5 34.5t-6.5 39.5z"/>
+</svg>
+\ No newline at end of file
diff --git a/src/lib/leaflet.control.mylocation/style.css b/src/lib/leaflet.control.mylocation/style.css
@@ -0,0 +1,37 @@
+.icon-position {
+ display: block;
+ position: absolute;
+ width: 60%;
+ height: 60%;
+ top: 20%;
+ left: 20%;
+ background-image: url("location-arrow.svg");
+ background-size: 100%;
+ background-repeat: no-repeat;
+ background-position: 50% 50%;
+}
+
+.following .icon-position {
+ background-image: url("location-arrow-active.svg");
+}
+
+.requesting .icon-position {
+ animation-name: spin;
+ animation-duration: 500ms;
+ animation-iteration-count: infinite;
+ animation-timing-function: linear;
+ animation-delay: 100ms;
+}
+
+@keyframes spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+.leaflet-control-locate.active a {
+ background-color: #cce8ff;
+}