index.js (5128B)
1 import L from 'leaflet'; 2 import {getSMap} from './apiLoader'; 3 import {CloseButtonMixin, DateLabelMixin, Events} from '../common'; 4 5 function getCoverageLayer(options) { 6 return L.tileLayer('https://mapserver.mapy.cz/panorama_hybrid-m/{z}-{x}-{y}', options); 7 } 8 9 async function getPanoramaAtPos(latlng, searchRadiusMeters) { 10 const smap = await getSMap(); 11 const request = smap.Pano.getBest(smap.Coords.fromWGS84(latlng.lng, latlng.lat), searchRadiusMeters); 12 try { 13 return { 14 found: true, 15 data: await request, 16 }; 17 } catch (e) { 18 return {found: false}; 19 } 20 } 21 22 const Viewer = L.Evented.extend({ 23 includes: [CloseButtonMixin, DateLabelMixin], 24 25 initialize: function(smap, container) { 26 // Disable keyboard events for panorama as they conflict with other hotkeys. 27 const orig_windowAddEventListener = window.addEventListener; 28 window.addEventListener = (function(type, ...args) { 29 if (!/^key/u.test(type)) { 30 orig_windowAddEventListener(type, ...args); 31 } 32 }); 33 this.panorama = new smap.Pano.Scene(container); 34 window.addEventListener = orig_windowAddEventListener; 35 this.createDateLabel(container); 36 this.createCloseButton(container); 37 window.addEventListener('resize', this.resize.bind(this)); 38 this.invalidateSize = L.Util.throttle(this._invalidateSize, 100, this); 39 this._updateHandler = null; 40 this._placeId = null; 41 this._yaw = null; 42 this._pitch = null; 43 this._fov = null; 44 this._yawPitchZoomChangeTimer = null; 45 }, 46 47 showPano: function(place, yaw = null, pitch = 0, fov = 1.256637061) { 48 if (yaw === null) { 49 yaw = this.panorama.getCamera().yaw; 50 } 51 this.panorama.show(place, {yaw}); 52 this.panorama.setCamera({fov, pitch}); 53 if (!this._updateHandler) { 54 this._updateHandler = setInterval(this.watchMapyStateChange.bind(this), 50); 55 } 56 }, 57 58 activate: function() { 59 this.resize(); 60 }, 61 62 deactivate: function() { 63 this._placeId = null; 64 this._yaw = null; 65 this._pitch = null; 66 this._fov = null; 67 clearInterval(this._updateHandler); 68 this._updateHandler = null; 69 }, 70 71 getState: function() { 72 const camera = this.panorama.getCamera(); 73 const place = this.panorama.getPlace(); 74 if (!place) { 75 return null; 76 } 77 const coords = place.getCoords().toWGS84(); 78 return [ 79 coords[1].toFixed(6), 80 coords[0].toFixed(6), 81 camera.yaw.toFixed(4), 82 camera.pitch.toFixed(4), 83 camera.fov.toFixed(4), 84 ]; 85 }, 86 87 setState: function(state) { 88 const lat = parseFloat(state[0]); 89 const lng = parseFloat(state[1]); 90 const yaw = parseFloat(state[2]); 91 const pitch = parseFloat(state[3]); 92 const fov = parseFloat(state[4]); 93 if (!isNaN(lat) && !isNaN(lng) && !isNaN(yaw) && !isNaN(pitch) && !isNaN(fov)) { 94 getPanoramaAtPos({lat, lng}, 0).then(({data: place, found}) => { 95 if (found) { 96 this.showPano(place, yaw, pitch, fov); 97 } 98 }); 99 return true; 100 } 101 return false; 102 }, 103 104 resize: function() { 105 this.panorama.syncPort(); 106 }, 107 108 watchMapyStateChange: function() { 109 const place = this.panorama.getPlace(); 110 if (!place) { 111 return; 112 } 113 const placeId = place.getId(); 114 if (this._placeId !== placeId) { 115 this._placeId = placeId; 116 const coords = place.getCoords().toWGS84(); 117 this.updateDateLabel(); 118 this.fire(Events.ImageChange, {latlng: L.latLng(coords[1], coords[0])}); 119 } 120 const camera = this.panorama.getCamera(); 121 if (this._yaw !== camera.yaw || this._pitch !== camera.pitch || this._fov !== camera.fov) { 122 if (this._yaw !== camera.yaw) { 123 this.fire(Events.BearingChange, {bearing: (this._yaw * 180) / Math.PI}); 124 } 125 this._yaw = camera.yaw; 126 this._pitch = camera.pitch; 127 this._fov = camera.fov; 128 if (this._yawPitchZoomChangeTimer !== null) { 129 clearTimeout(this._yawPitchZoomChangeTimer); 130 this._yawPitchZoomChangeTimer = null; 131 } 132 this._yawPitchZoomChangeTimer = setTimeout(() => { 133 this.fire(Events.YawPitchZoomChangeEnd); 134 }, 120); 135 } 136 }, 137 138 updateDateLabel: function() { 139 const place = this.panorama.getPlace(); 140 const timestamp = Date.parse(place.getDate()); 141 DateLabelMixin.updateDateLabel.call(this, timestamp); 142 }, 143 144 _invalidateSize: function() { 145 this.panorama.syncPort(); 146 } 147 }); 148 149 async function getViewer(container) { 150 const smap = await getSMap(); 151 return new Viewer(smap, container); 152 } 153 154 const mapyczProvider = {getCoverageLayer, getPanoramaAtPos, getViewer}; 155 export default mapyczProvider;