nakarte

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

commit 55ddab38179d53526ef478127d4d5e8bc5e1c396
parent 943179b0bba21436c8b32914902aaf20ee18b5bd
Author: Sergej Orlov <wladimirych@gmail.com>
Date:   Thu, 10 Nov 2016 22:23:50 +0300

added google layers

Diffstat:
Msrc/config.js | 3++-
Msrc/layers.js | 8++++----
Asrc/lib/googleMapsApi/googleMapsApi.js | 30++++++++++++++++++++++++++++++
Asrc/lib/layer.google/google.js | 173+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 209 insertions(+), 5 deletions(-)

diff --git a/src/config.js b/src/config.js @@ -1,3 +1,4 @@ export default { - email: 'nakarte@nakarte.tk' + email: 'nakarte@nakarte.tk', + googleApiUrl: 'https://maps.googleapis.com/maps/api/js?v=3&sensor=false' } diff --git a/src/layers.js b/src/layers.js @@ -1,5 +1,6 @@ import L from "leaflet"; -import './lib/layer.yandex/yandex'; +import 'lib/layer.yandex/yandex'; +import 'lib/layer.google/google'; function getBaseMaps() { // var bingKey = 'AhZy06XFi8uAADPQvWNyVseFx4NHYAOH-7OTMKDPctGtYo86kMfx2T0zUrF5AAaM'; @@ -13,9 +14,8 @@ function getBaseMaps() { ), 'Yandex': new L.Layer.Yandex('map', {scaleDependent: true, code: 'Y', print: true, jnx: true}), 'Yandex Sat': new L.Layer.Yandex('sat', {scaleDependent: false, code: 'S', print: true, jnx: true}), - // 'Google': new L.Google('ROADMAP', {code: 'G', scaleDependent: true, print: true, jnx: true}), - // 'Google Sat': new L.Google('SATELLITE', {code: 'L', print: true, jnx: true}), - // 'Google Sat Hybrid': new L.Google('HYBRID', {code: 'H', scaleDependent: true, print: true, jnx: false}), + 'Google': new L.Layer.Google('ROADMAP', {code: 'G', scaleDependent: true, print: true, jnx: true}), + 'Google Sat': new L.Layer.Google('SATELLITE', {code: 'L', print: true, jnx: true}), // 'Bing Sat': L.bingLayer(bingKey, {code: 'I', print: true, jnx: true}), 'marshruty.ru': L.tileLayer('http://maps.marshruty.ru/ml.ashx?x={x}&y={y}&z={z}&i=1&al=1', {code: 'M', maxNativeZoom: 18, noCors: true, scaleDependent: true, print: true, jnx: true} diff --git a/src/lib/googleMapsApi/googleMapsApi.js b/src/lib/googleMapsApi/googleMapsApi.js @@ -0,0 +1,29 @@ +import loadScript from 'load-script'; +import config from 'config'; + +let _google = null; +let _pending = null; + +function getGoogle() { + if (_google) { + return Promise.resolve(_google); + } + if (!_pending) { + _pending = new Promise((resolve, reject) => { + loadScript(config.googleApiUrl, (error) => { + if (error) { + reject(error) + } + _google = window.google; + resolve(_google); + } + ); + + } + ); + } + return _pending; +} + + +export default getGoogle; +\ No newline at end of file diff --git a/src/lib/layer.google/google.js b/src/lib/layer.google/google.js @@ -0,0 +1,173 @@ +import L from 'leaflet'; +import getGoogle from 'lib/googleMapsApi/googleMapsApi'; + +L.Layer.Google = L.GridLayer.extend({ + options: {}, + + // Possible types: SATELLITE, ROADMAP, HYBRID, TERRAIN + initialize: function(mapType, options) { + L.GridLayer.prototype.initialize.call(this, options); + L.Layer.prototype.constructor(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) => { + this.google = google; + this._googleMap = new google.maps.Map(this._googleMapContainer, { + center: new google.maps.LatLng(0, 0), + zoom: 0, + tilt: 0, + mapTypeId: google.maps.MapTypeId[this.mapType], + disableDefaultUI: true, + keyboardShortcuts: false, + draggable: false, + disableDoubleClickZoom: true, + scrollwheel: false, + streetViewControl: false, + clickableIcons: false + } + ); + google.maps.event.addListener(this._googleMap, 'tilesloaded', this._onTilesLoaded.bind(this)); + setTimeout(this._syncPosition.bind(this), 0); + } + ); + map.on({ + viewreset: this._clearTiles, + 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(); + map.getContainer().removeChild(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) { + return; + } + let center = this._map.getCenter(); + setTimeout(() => { + let googleCenter = new this.google.maps.LatLng(center.lat, center.lng); + this._googleMap.setCenter(googleCenter); + this._googleMap.setZoom(this._map.getZoom()); + }, 0 + ); + }, + + _onZoom: function(e) { + let center = e.center; + setTimeout(() => { + let googleCenter = new window.google.maps.LatLng(center.lat, center.lng); + 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(); + }, + + _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; + }, + + _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]; + } + } + }, + + _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); + } + }, + + _tileOnError: function(done, tile, e) { + done(e, tile); + }, + + 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; + } + } +);