nakarte

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

commit 980496eaadedd8367f90df4505d68e8eb91ae569
parent 369dd570de9de31f1b88b4ef2d6c16e5ca86a073
Author: Sergej Orlov <wladimirych@gmail.com>
Date:   Mon, 21 Nov 2016 00:39:06 +0300

added panoramas control

Diffstat:
Mpublic/index.html | 1+
Msrc/App.css | 14++++++++++++--
Msrc/App.js | 4+++-
Asrc/lib/leaflet.control.panoramas/binocualar.png | 0
Asrc/lib/leaflet.control.panoramas/panoramas-off.png | 0
Asrc/lib/leaflet.control.panoramas/panoramas-on.png | 0
Asrc/lib/leaflet.control.panoramas/panoramas.js | 248+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/lib/leaflet.control.panoramas/style.css | 24++++++++++++++++++++++++
8 files changed, 288 insertions(+), 3 deletions(-)

diff --git a/public/index.html b/public/index.html @@ -16,6 +16,7 @@ <title>nakarte.tk</title> </head> <body> + <div id="street-view"></div> <div id="map"></div> </body> </html> diff --git a/src/App.css b/src/App.css @@ -1,3 +1,14 @@ #map { height: 100%; -} -\ No newline at end of file +} + +#street-view { + width: 50%; + height: 100%; + float: left; + display: none; +} + +#street-view.enabled { + display: block; +} diff --git a/src/App.js b/src/App.js @@ -12,7 +12,7 @@ import 'lib/leaflet.hashState/Leaflet.Map'; import 'lib/leaflet.hashState/Leaflet.Control.Layers'; import fixAnimationBug from 'lib/leaflet.fixAnimationBug/leaflet.fixAnimationBug' import './adaptive.css'; - +import 'lib/leaflet.control.panoramas/panoramas'; function autoSizeControl(map, control) { // для контрола Layers есть аналогичная функция при разворачивании из кнопки. @@ -68,7 +68,9 @@ function setUp() { new L.Control.PrintPages({position: 'bottomleft'}).addTo(map); new L.Control.Coordinates().addTo(map); + const panoramas = new L.Control.Panoramas(document.getElementById('street-view')).addTo(map); + panoramas.enableHashState('n'); map.on('resize', autoSizeControl.bind(null, map, layersControl)); autoSizeControl(map, layersControl); diff --git a/src/lib/leaflet.control.panoramas/binocualar.png b/src/lib/leaflet.control.panoramas/binocualar.png Binary files differ. diff --git a/src/lib/leaflet.control.panoramas/panoramas-off.png b/src/lib/leaflet.control.panoramas/panoramas-off.png Binary files differ. diff --git a/src/lib/leaflet.control.panoramas/panoramas-on.png b/src/lib/leaflet.control.panoramas/panoramas-on.png Binary files differ. diff --git a/src/lib/leaflet.control.panoramas/panoramas.js b/src/lib/leaflet.control.panoramas/panoramas.js @@ -0,0 +1,247 @@ +import L from 'leaflet'; +import './style.css'; +import getGoogle from 'lib/googleMapsApi/googleMapsApi'; + + +L.Control.Panoramas = L.Control.extend({ + includes: L.Mixin.Events, + + options: { + position: 'topleft' + }, + + initialize: function(panoramaContainer, options) { + L.Control.prototype.initialize.call(this, options); + this._panoramaContainer = panoramaContainer; + + const icon = L.divIcon({ + className: 'leaflet-panorama-marker-wraper', + html: '<div class="leaflet-panorama-marker"></div>' + } + ); + this.marker = L.marker([0, 0], {icon: icon}); + }, + + onAdd: function(map) { + this._map = map; + this.initPanoramaApi(); + const container = L.DomUtil.create('a', 'leaflet-control leaflet-contol-button leaflet-contol-panoramas'); + container.title = 'Show panoramas'; + L.DomEvent.disableClickPropagation(container); + if (!L.Browser.touch) { + L.DomEvent.disableScrollPropagation(container); + } + L.DomEvent.on(container, 'click', this.onButtonClick, this); + + map.createPane('rasterOverlay').style.zIndex = 300; + this._coverageLayer = L.tileLayer( + 'https://mts1.googleapis.com/vt?lyrs=svv|cb_client:apiv3&style=40,18&x={x}&y={y}&z={z}', + {pane: 'rasterOverlay'} + ); + + return container; + }, + + onRemove: function() { + this._map = null; + this.hideCoverage(); + this.hidePanorama(); + }, + + showPanorama: function() { + if (this.panoramaVisible) { + return; + } + L.DomUtil.addClass(this._panoramaContainer, 'enabled'); + this.panoramaApi.then((api) => api.panorama.setVisible(true)); + window.dispatchEvent(new Event('resize')); + this.marker.addTo(this._map); + this.panoramaVisible = true; + this.notifyChanged(); + }, + + hidePanorama: function() { + if (!this.panoramaVisible) { + return; + } + this.panoramaApi.then((api) => api.panorama.setVisible(false)); + L.DomUtil.removeClass(this._panoramaContainer, 'enabled'); + window.dispatchEvent(new Event('resize')); + this._map.removeLayer(this.marker); + this.panoramaVisible = false; + this.notifyChanged(); + }, + + showCoverage: function() { + if (this.coverageVisible) { + return; + } + L.DomUtil.addClass(this.getContainer(), 'enabled'); + this._coverageLayer.addTo(this._map); + this._map.on('click', this.onMapClick, this); + this.coverageVisible = true; + this.notifyChanged(); + }, + + onMapClick: function(e) { + this.showPanoramaAtPos(e.latlng); + }, + + showPanoramaAtPos: function(latlng, pov) { + this.showPanorama(); + const searchRadiusPx = 24; + const p = this._map.project(latlng).add([searchRadiusPx, 0]); + const searchRadiusMeters = latlng.distanceTo(this._map.unproject(p)); + + function setPanoramaPosition(api, panoData, status) { + if (status === api.google.maps.StreetViewStatus.OK) { + api.panorama.setPosition(panoData.location.latLng); + } + if (pov) { + api.panorama.setPov(pov); + } + } + + this.panoramaApi.then((api) => { + api.service.getPanorama({ + location: latlng, + radius: searchRadiusMeters, + preference: api.google.maps.StreetViewPreference.NEAREST + }, setPanoramaPosition.bind(null, api) + ); + } + ); + }, + + hideCoverage: function() { + if (!this.coverageVisible) { + return; + } + L.DomUtil.removeClass(this.getContainer(), 'enabled'); + this._coverageLayer.removeFrom(this._map); + this._map.off('click', this.onMapClick, this); + this.coverageVisible = false; + this.notifyChanged(); + }, + + onButtonClick: function() { + if (!this.coverageVisible) { + this.showCoverage(); + } else { + this.hideCoverage(); + this.hidePanorama(); + } + }, + + onPanoramaChangePosition: function() { + this.panoramaApi.then((api) => { + let pos = api.panorama.getPosition(); + if (pos) { + pos = L.latLng([pos.lat(), pos.lng()]); + this.marker.setLatLng(pos); + if (!this._map.getBounds().contains(pos)) { + this._map.panTo(pos); + } + this.panoramaPosition = pos; + } else { + this.panoramaPosition = null; + } + this.notifyChanged(); + } + ); + }, + + onPanoramaChangeView: function() { + let markerIcon = this.marker.getElement(); + if (markerIcon) { + markerIcon = markerIcon.children[0] + } + this.panoramaApi.then((api) => { + const pov = api.panorama.getPov(); + if (markerIcon) { + markerIcon.style.transform = `rotate(${pov.heading}deg)`; + } + this.panoramaAngle = pov; + this.notifyChanged(); + } + ); + }, + + notifyChanged: function() { + this.fire('panoramachanged') + }, + + initPanoramaApi: function() { + if (this.panoramaApi) { + return; + } + this.panoramaApi = getGoogle().then((google) => { + const panorama = new google.maps.StreetViewPanorama(this._panoramaContainer, { + enableCloseButton: true, + imageDateControl: true + } + ); + panorama.addListener('position_changed', this.onPanoramaChangePosition.bind(this)); + panorama.addListener('pov_changed', this.onPanoramaChangeView.bind(this)); + panorama.addListener('closeclick', this.hidePanorama.bind(this)); + + return { + google, + service: new google.maps.StreetViewService(), + panorama + + } + } + ) + } + } +); + +L.Control.Panoramas.include(L.Mixin.HashState); +L.Control.Panoramas.include({ + stateChangeEvents: ['panoramachanged'], + + serializeState: function() { + if (!this.coverageVisible) { + return []; + } + const state = []; + if (this.panoramaVisible) { + state.push('1'); + if (this.panoramaPosition && this.panoramaAngle !== undefined) { + state.push(this.panoramaPosition.lat.toFixed(5)); + state.push(this.panoramaPosition.lng.toFixed(5)); + state.push(Math.round(this.panoramaAngle.heading).toFixed()); + state.push(Math.round(this.panoramaAngle.pitch).toFixed()); + state.push(Math.round(this.panoramaAngle.zoom).toFixed(2)); + } + } else { + state.push('0'); + } + return state; + }, + + unserializeState: function(state) { + if (!state || !state.length) { + this.hidePanorama(); + this.hideCoverage(); + return; + } + if (state[0] === '1') { + this.showCoverage(); + const lat = parseFloat(state[1]); + const lng = parseFloat(state[2]); + const heading = parseFloat(state[3]); + const pitch = parseFloat(state[4]); + const zoom = parseFloat(state[5]); + if (!isNaN(lat) && !isNaN(lng) && !isNaN(heading) && !isNaN(pitch)) { + this.showPanoramaAtPos(L.latLng(lat, lng), {heading, pitch, zoom}); + } + + } else { + this.hidePanorama(); + this.showCoverage(); + } + } + } +); +\ No newline at end of file diff --git a/src/lib/leaflet.control.panoramas/style.css b/src/lib/leaflet.control.panoramas/style.css @@ -0,0 +1,23 @@ +.leaflet-contol-panoramas { + background-image: url('panoramas-off.png'); +} + +.leaflet-contol-panoramas.enabled { + background-image: url('panoramas-on.png'); +} + +.leaflet-panorama-marker-wraper { + width: 0 !important; + height: 0 !important; + margin: 0 !important; +} + +.leaflet-panorama-marker { + background-image: url("binocualar.png"); + width: 31px; + height: 31px; + margin-left: -17px; + margin-top: -17px; + /*transform-origin: 17px 17px;*/ + +} +\ No newline at end of file