nakarte

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

commit 5ea8f75aaa007f755b697c5449d54e6850a16ddb
parent 5b8185eb22a588daa5218fcff5fb41c3e4225f3a
Author: Sergej Orlov <wladimirych@gmail.com>
Date:   Thu,  7 Nov 2019 22:04:14 +0100

google: replace complex API-based layers with simple tile layers

Solution inspired by SAS planet.
Also add Google Hybrid overlay.

Diffstat:
Msrc/layers.js | 24++++++++++++++++++++----
Msrc/lib/leaflet.layer.google/index.js | 229+++++++++++++++----------------------------------------------------------------
Msrc/lib/leaflet.layer.rasterize/Google.js | 42++----------------------------------------
3 files changed, 66 insertions(+), 229 deletions(-)

diff --git a/src/layers.js b/src/layers.js @@ -74,7 +74,7 @@ export default function getLayers() { { title: 'Google', isDefault: true, - layer: new L.Layer.Google('ROADMAP', + layer: new L.Layer.GoogleMap( { code: 'G', isOverlay: false, @@ -86,9 +86,24 @@ export default function getLayers() { ) }, { + title: 'Google Hybrid', + isDefault: true, + layer: new L.Layer.GoogleHybrid( + { + code: 'Gh', + isOverlay: true, + scaleDependent: true, + print: true, + jnx: false, + shortName: 'google_hybrid', + isOverlayTransparent: true + } + ) + }, + { title: 'Google Satellite', isDefault: true, - layer: new L.Layer.Google('SATELLITE', + layer: new L.Layer.GoogleSat( { code: 'L', isOverlay: false, @@ -102,8 +117,7 @@ export default function getLayers() { { title: 'Google Terrain', isDefault: true, - layer: new L.Layer.Google('TERRAIN', - { + layer: new L.Layer.GoogleTerrain({ code: 'P', isOverlay: false, scaleDependent: false, @@ -996,6 +1010,7 @@ export default function getLayers() { { title: 'Miscellaneous', layers: [ + 'Google Hybrid', 'Mountains by Aleksey Tsvetkov', 'Bing imagery acquisition dates', 'geocaching.su'] @@ -1089,6 +1104,7 @@ export default function getLayers() { '#custom-top', // line overlays + 'Google Hybrid', 'Waymarked Hiking Trails', 'Waymarked Cycling Trails', 'Bing imagery acquisition dates', diff --git a/src/lib/leaflet.layer.google/index.js b/src/lib/leaflet.layer.google/index.js @@ -1,192 +1,51 @@ -import L from 'leaflet'; -import getGoogle from 'lib/googleMapsApi'; -import logging from 'lib/logging'; - -L.Layer.Google = L.GridLayer.extend({ - options: {}, - - // Possible types: SATELLITE, ROADMAP, HYBRID, TERRAIN - initialize: function(mapType, options) { - L.GridLayer.prototype.initialize.call(this, options); - this.mapType = mapType; - }, - - onAdd: function(map) { - this._clearTiles(); - L.GridLayer.prototype.onAdd.call(this, map); - this._googleMapContainer = L.DomUtil.create('div', '', map.getContainer()); - this._googleMapContainer.style.width = '100%'; - this._googleMapContainer.style.height = '100%'; - // this._googleMapContainer.style.opacity = 0; - this._googleMapContainer.style.visibility = 'hidden'; - this._googleMapContainer.style.pointerEvents = 'none'; - getGoogle().then((google) => { - let zoom, center; - if (map) { - zoom = map.getZoom(); - center = map.getCenter; - center = new google.maps.LatLng(center.lat, center.lng); - } else { - zoom = 0; - center = new google.maps.LatLng(0, 0); - } - this.google = google; - this._googleMap = new google.maps.Map(this._googleMapContainer, { - center: center, - zoom: zoom, - tilt: 0, - mapTypeId: google.maps.MapTypeId[this.mapType], - disableDefaultUI: true, - keyboardShortcuts: false, - draggable: false, - disableDoubleClickZoom: true, - scrollwheel: false, - streetViewControl: false, - clickableIcons: false - } - ); - logging.logEvent('googleMapLoad'); - google.maps.event.addListener(this._googleMap, 'tilesloaded', this._onTilesLoaded.bind(this)); - setTimeout(this._syncPosition.bind(this), 0); - } - ); - map.on({ - viewreset: this._syncPosition, - resize: this._onResize, - move: this._syncPosition, - zoomanim: this._onZoom - }, this - ); - }, - - onRemove: function(map) { - if (this.google) { - this.google.maps.event.clearInstanceListeners(this._googleMap); - } - this._googleMap = null; - this._clearTiles(); - L.DomUtil.remove(this._googleMapContainer); - map.off({ - viewreset: this._clearTiles, - resize: this._onResize, - move: this._syncPosition, - zoomanim: this._onZoom - }, this - ); - L.GridLayer.prototype.onRemove.call(this, map); - }, - - _clearTiles: function() { - this._pendingTiles = {}; - this._readyTiles = {}; - }, - - _onResize: function() { - if (!this.google) { - return; - } - this.google.maps.event.trigger(this._googleMap, 'resize'); - }, - - _syncPosition: function() { - if (!this.google || !this._map) { - return; - } - let center = this._map.getCenter(); - let googleCenter = new this.google.maps.LatLng(center.lat, center.lng); - setTimeout(() => { - if (!this._googleMap) { - return; - } - this._googleMap.setCenter(googleCenter); - this._googleMap.setZoom(this._map.getZoom()); - }, 0 - ); - }, - - _onZoom: function(e) { - if (!this.google) { - return; - } - let center = e.center; - let googleCenter = new this.google.maps.LatLng(center.lat, center.lng); - setTimeout(() => { - if (!this._googleMap) { - return; - } - this._googleMap.setCenter(googleCenter); - this._googleMap.setZoom(Math.round(e.zoom)); - }, 0 - ); - }, - - _roadRegexp: /!1i(\d+)!2i(\d+)!3i(\d+)!/, - _satRegexp: /x=(\d+)&y=(\d+)&z=(\d+)/, - - _onTilesLoaded: function() { - this._readyTiles = this._collectMapImageElements(); - this._fullfillPendingTiles(); - }, +import L from "leaflet"; + +L.Layer.GoogleBase = L.TileLayer.extend({ + options: { + subdomains: '0123' + }, + + getTileUrl: function(coords) { + const data = { + x: coords.x, + y: coords.y, + z: 17 - this._getZoomForUrl(), + s: this._getSubdomain(coords), + lang: navigator.language || '' + }; + return L.Util.template(this._url, data); + } +}); - _collectMapImageElements: function() { - const images = this._googleMapContainer.getElementsByTagName('img'); - const tiles = {}; - for (let image of [...images]) { - let url = image.src; - let match, coords; - match = url.match(this._roadRegexp); - if (match) { - coords = {z: match[1], x: match[2], y: match[3]} - } else { - match = url.match(this._satRegexp); - if (match) { - coords = {x: match[1], y: match[2], z: match[3]} - } - } - if (coords) { - tiles[this._tileCoordsToKey(coords)] = url; - } - } - return tiles; - }, +L.Layer.GoogleMap = L.Layer.GoogleBase.extend({ + initialize: function(options) { + L.Layer.GoogleBase.prototype.initialize.call( + this, 'https://mt{s}.google.com/vt/lyrs=m@169000000&hl={lang}&x={x}&y={y}&zoom={z}', options); + } +}); - _fullfillPendingTiles: function() { - for (let key of Object.keys(this._readyTiles)) { - if (key in this._pendingTiles) { - for (let [img, cb] of this._pendingTiles[key]) { - L.DomEvent.on(img, 'load', L.bind(this._tileOnLoad, this, cb, img)); - L.DomEvent.on(img, 'error', L.bind(this._tileOnError, this, cb, img)); - img.alt = ''; - img.src = this._readyTiles[key]; - } - delete this._pendingTiles[key]; - } - } - }, +L.Layer.GoogleTerrain = L.Layer.GoogleBase.extend({ + initialize: function(options) { + L.Layer.GoogleBase.prototype.initialize.call( + this, 'https://mt{s}.google.com/vt/lyrs=t@130,r@206000000&hl={lang}&x={x}&y={y}&zoom={z}', options); + } +}); - _tileOnLoad: function(done, tile) { - // For https://github.com/Leaflet/Leaflet/issues/3332 - if (L.Browser.ielt9) { - setTimeout(L.bind(done, this, null, tile), 0); - } else { - done(null, tile); - } - }, +L.Layer.GoogleHybrid = L.Layer.GoogleBase.extend({ + initialize: function(options) { + L.Layer.GoogleBase.prototype.initialize.call( + this, 'https://mt{s}.google.com/vt/lyrs=h@169000000&hl={lang}&x={x}&y={y}&zoom={z}', options); + } +}); - _tileOnError: function(done, tile, e) { - done(e, tile); - }, +L.Layer.GoogleSat = L.TileLayer.extend({ + options: { + subdomains: '0123' + }, - createTile: function(coords, done) { - const tile = L.DomUtil.create('img'); - const key = this._tileCoordsToKey(coords); - if (!(key in this._pendingTiles)) { - this._pendingTiles[key] = []; - } - this._pendingTiles[key].push([tile, done]); - setTimeout(this._fullfillPendingTiles.bind(this), 0); - return tile; - } + initialize: function(options) { + L.TileLayer.prototype.initialize.call( + this, 'https://mt{s}.google.com/vt/lyrs=s&x={x}&y={y}&z={z}', options) } -); +}); diff --git a/src/lib/leaflet.layer.rasterize/Google.js b/src/lib/leaflet.layer.rasterize/Google.js @@ -1,47 +1,9 @@ import L from 'leaflet'; import 'lib/leaflet.layer.google'; -import {TileLayerGrabMixin} from './TileLayer'; - - -const GooglePrint = L.Layer.Google.extend({ - includes: TileLayerGrabMixin, - - _rasterizeNeedsFullSizeMap: true, - - _dummyTile: L.DomUtil.create('div'), - - onAdd: function(map) { - this._waitTilesReadyToGrab = new Promise((resolve) => { - this._tilesReadyToGrab = resolve; - }); - L.Layer.Google.prototype.onAdd.call(this, map); - }, - - waitTilesReadyToGrab: function() { - return this._waitTilesReadyToGrab; - }, - - createTile: function() { - return this._dummyTile; - }, - - _fullfillPendingTiles: function() { - if (!Object.keys(this._readyTiles).length) { - return; - } - this._tilesReadyToGrab(); - }, - - getTileUrl: function(coords) { - return this._readyTiles[this._tileCoordsToKey(coords)] || null; - } -}); - - -L.Layer.Google.include({ +L.Layer.GoogleBase.include({ cloneForPrint: function(options) { - return new GooglePrint(this.mapType, L.Util.extend({}, this.options, options)); + return new L.Layer.GoogleBase(this._url, L.Util.extend({}, this.options, options)); }, });