nakarte

Source code of https://map.sikmir.ru (fork)
git clone git://git.sikmir.ru/nakarte
Log | Files | Refs | LICENSE

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:
Msrc/App.js | 3+++
Asrc/lib/leaflet.control.external-maps/external-link.svg | 3+++
Asrc/lib/leaflet.control.external-maps/index.js | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/lib/leaflet.control.external-maps/style.css | 3+++
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"); +}