commit 88b2516f7705aa615f8ec04b389114fbdb3a058f
parent bd3219b0bb0fd4238a50469e55acb487acf72924
Author: Sergey Orlov <wladimirych@gmail.com>
Date: Sat, 27 Jun 2020 22:14:21 +0200
add new tool: open current view in other mapping sites
Diffstat:
4 files changed, 110 insertions(+), 0 deletions(-)
diff --git a/src/App.js b/src/App.js
@@ -32,6 +32,7 @@ import {notify} from '~/lib/notifications';
import ZoomDisplay from '~/lib/leaflet.control.zoom-display';
import logging from '~/lib/logging';
import safeLocalStorage from '~/lib/safe-localstorage';
+import {ExternalMaps} from '~/lib/leaflet.control.external-maps/index.js';
const locationErrorMessage = {
0: 'Your browser does not support geolocation.',
@@ -74,6 +75,8 @@ function setUp() {
stackHorizontally: true
}).addTo(map);
+ new ExternalMaps({position: 'topleft'}).addTo(map);
+
new L.Control.TrackList.Ruler(tracklist).addTo(map);
const panoramas = new L.Control.Panoramas()
diff --git a/src/lib/leaflet.control.external-maps/external-link.svg b/src/lib/leaflet.control.external-maps/external-link.svg
@@ -0,0 +1,3 @@
+<svg fill="#333" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
+ <path d="M 25.980469 2.9902344 A 1.0001 1.0001 0 0 0 25.869141 3 L 20 3 A 1.0001 1.0001 0 1 0 20 5 L 23.585938 5 L 13.292969 15.292969 A 1.0001 1.0001 0 1 0 14.707031 16.707031 L 25 6.4140625 L 25 10 A 1.0001 1.0001 0 1 0 27 10 L 27 4.1269531 A 1.0001 1.0001 0 0 0 25.980469 2.9902344 z M 6 7 C 4.9069372 7 4 7.9069372 4 9 L 4 24 C 4 25.093063 4.9069372 26 6 26 L 21 26 C 22.093063 26 23 25.093063 23 24 L 23 14 L 23 11.421875 L 21 13.421875 L 21 16 L 21 24 L 6 24 L 6 9 L 14 9 L 16 9 L 16.578125 9 L 18.578125 7 L 16 7 L 14 7 L 6 7 z"/>
+</svg>
diff --git a/src/lib/leaflet.control.external-maps/index.js b/src/lib/leaflet.control.external-maps/index.js
@@ -0,0 +1,101 @@
+import L from 'leaflet';
+import {makeButton} from '~/lib/leaflet.control.commons';
+import Contextmenu from '~/lib/contextmenu';
+import {ElevationProvider} from '~/lib/elevations';
+import logging from '~/lib/logging';
+
+import './style.css';
+
+class ExternalMap {
+ constructor(urlTemplate, minZoom, maxZoom) {
+ this.url = urlTemplate;
+ this.minZoom = minZoom;
+ this.maxZoom = maxZoom;
+ }
+
+ async getData(map_) {
+ const {lat, lng} = map_.getCenter();
+ let zoom = map_.getZoom();
+ zoom = Math.min(this.maxZoom, zoom);
+ zoom = Math.max(this.minZoom, zoom);
+ return {lat, lng, zoom};
+ }
+
+ async getUrl(map_) {
+ return L.Util.template(this.url, await this.getData(map_));
+ }
+}
+
+class GoogleEarthMap extends ExternalMap {
+ constructor() {
+ super('https://earth.google.com/web/@{lat},{lng},0a,{dist}d,35y,0h,0t,0r', 0, 100);
+ }
+
+ async getData(map_) {
+ const data = await super.getData(map_);
+ const windowSize = window.innerHeight;
+ const earthPerimeter = 40075016;
+ const degree = Math.PI / 180;
+ const viewAngle = 35;
+ let elevation;
+ try {
+ elevation = (await new ElevationProvider().get([data]))[0];
+ } catch (e) {
+ elevation = 8000;
+ logging.captureException(e, 'failed to get elevation for GoogleEarth link');
+ }
+ const mercatorPixelSize = (earthPerimeter / (256 * 2 ** data.zoom)) * Math.cos(data.lat * degree);
+ const distInPixels = windowSize / 2 / Math.tan((viewAngle * degree) / 2);
+ data.dist = distInPixels * mercatorPixelSize + elevation;
+ return data;
+ }
+}
+
+const ExternalMaps = L.Control.extend({
+ options: {
+ externalMaps: [
+ {title: 'Google', externalMap: new ExternalMap('https://www.google.com/maps/@{lat},{lng},{zoom}z', 3, 21)},
+ {
+ title: 'Yandex',
+ externalMap: new ExternalMap('https://yandex.ru/maps/10509/brno/?ll={lng}%2C{lat}&z={zoom}', 2, 21),
+ },
+ {
+ title: 'OpenStreetMap',
+ externalMap: new ExternalMap('https://www.openstreetmap.org/#map={zoom}/{lat}/{lng}', 0, 19),
+ },
+ {title: 'Google Earth 3D', externalMap: new GoogleEarthMap()},
+ {
+ title: 'Mapy.cz',
+ externalMap: new ExternalMap('https://en.mapy.cz/turisticka?x={lng}&y={lat}&z={zoom}', 2, 19),
+ },
+ ],
+ },
+
+ onAdd: function(map) {
+ this._map = map;
+ const {container, link} = makeButton(null, 'Open external map', 'icon-external-links');
+ this._container = container;
+ L.DomEvent.on(link, 'click contextmenu', this.onClick, this);
+
+ const menuItems = [
+ {text: 'Open this place on external map', header: true},
+ ...this.options.externalMaps.map((it) => ({
+ text: it.title,
+ callback: this.openExternalMap.bind(this, it.externalMap),
+ })),
+ ];
+ this.menu = new Contextmenu(menuItems);
+ return container;
+ },
+
+ onClick: function(e) {
+ this.menu.show(e);
+ },
+
+ async openExternalMap(externalMap) {
+ const url = await externalMap.getUrl(this._map);
+ window.open(url, '_blank');
+ },
+});
+
+export {ExternalMaps};
diff --git a/src/lib/leaflet.control.external-maps/style.css b/src/lib/leaflet.control.external-maps/style.css
@@ -0,0 +1,3 @@
+.icon-external-links {
+ background-image: url("external-link.svg");
+}