commit 980496eaadedd8367f90df4505d68e8eb91ae569
parent 369dd570de9de31f1b88b4ef2d6c16e5ca86a073
Author: Sergej Orlov <wladimirych@gmail.com>
Date: Mon, 21 Nov 2016 00:39:06 +0300
added panoramas control
Diffstat:
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