nakarte

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

index.js (5828B)


      1 import L from 'leaflet';
      2 
      3 import config from '~/config';
      4 
      5 import {getPanorama} from './apiLoader';
      6 import {CloseButtonMixin, Events} from '../common';
      7 
      8 function getCoverageLayer(options) {
      9     return L.tileLayer('https://proxy.nakarte.me/mapy/panorama_ln_hybrid-m/{z}-{x}-{y}', options);
     10 }
     11 
     12 async function getPanoramaAtPos(latlng, searchRadiusMeters) {
     13     const panoramaClass = await getPanorama();
     14     const res = await panoramaClass.panoramaExists({
     15         lon: latlng.lng,
     16         lat: latlng.lat,
     17         radius: searchRadiusMeters,
     18         apiKey: config.mapyCzKey,
     19     });
     20     return {
     21         found: res.exists,
     22         data: res.info,
     23     };
     24 }
     25 
     26 const MapyPanoramaWrapper = L.Evented.extend({
     27     initialize: function (mapyPanorama, container, apiKey) {
     28         this.apiKey = apiKey;
     29         this.container = L.DomUtil.create('div', null, container);
     30         this.container.style.height = '100%';
     31         this.mapyPanorama = mapyPanorama;
     32         this.viewerControl = null;
     33         this.position = null;
     34         this.pov = null;
     35     },
     36 
     37     deactivate: function () {
     38         this.reset();
     39         this.position = null;
     40         this.pov = null;
     41     },
     42     showPano: async function (position, pov) {
     43         this.reset();
     44         this.position = null;
     45         // Disable keyboard events for panorama as they  conflict with other hotkeys.
     46         const origWindowAddEventListener = window.addEventListener;
     47         window.addEventListener = function (type, ...args) {
     48             if (!/^key/u.test(type)) {
     49                 origWindowAddEventListener(type, ...args);
     50             }
     51         };
     52         let res;
     53         try {
     54             res = await this.mapyPanorama.panoramaFromPosition({
     55                 parent: this.container,
     56                 ...position,
     57                 ...(pov ?? this.pov ?? {yaw: 'auto'}),
     58                 radius: 0.01,
     59                 showNavigation: true,
     60                 apiKey: this.apiKey,
     61                 lang: 'en',
     62             });
     63         } finally {
     64             window.addEventListener = origWindowAddEventListener; // eslint-disable-line require-atomic-updates
     65         }
     66         if (res.error) {
     67             return;
     68         }
     69         this.viewerControl = res;
     70         this.onPositionChange(res);
     71         const loadedPanoPov = res.getCamera();
     72         this.onPOVChange(loadedPanoPov);
     73         this.viewerControl.addListener('pano-view', this.onPOVChange.bind(this));
     74         this.viewerControl.addListener('pano-place', this.onPositionChange.bind(this));
     75     },
     76 
     77     reset: function () {
     78         if (this.viewerControl) {
     79             this.viewerControl.destroy();
     80             this.viewerControl = null;
     81         }
     82     },
     83 
     84     onPOVChange: function (pov) {
     85         this.pov = pov;
     86         this.notifyViewChanged(pov);
     87     },
     88 
     89     onPositionChange: function (e) {
     90         this.position = e.info;
     91         this.notifyPositionChanged(e.info);
     92     },
     93 
     94     notifyPositionChanged: function (position) {
     95         this.fire('position-change', position);
     96     },
     97 
     98     notifyViewChanged: function (pov) {
     99         this.fire('view-change', pov);
    100     },
    101 
    102     getPanoramaCoords: function () {
    103         return this.position;
    104     },
    105 
    106     getPov: function () {
    107         if (this.viewerControl === null) {
    108             return null;
    109         }
    110         return this.viewerControl.getCamera();
    111     },
    112 });
    113 
    114 const Viewer = L.Evented.extend({
    115     includes: [CloseButtonMixin],
    116 
    117     initialize: function (mapyPanorama, container) {
    118         this.mapyPanoramaWrapper = new MapyPanoramaWrapper(mapyPanorama, container, config.mapyCzKey);
    119         this.createCloseButton(container);
    120         this.mapyPanoramaWrapper.on('position-change', this.onPanoramaPositionChanged, this);
    121         this.mapyPanoramaWrapper.on('view-change', this.onPanoramaPovChanged, this);
    122         this.povChangeTimer = null;
    123     },
    124 
    125     showPano: function (place, pov) {
    126         this.mapyPanoramaWrapper.showPano(place, pov);
    127     },
    128 
    129     activate: function () {
    130         // no action needed
    131     },
    132 
    133     deactivate: function () {
    134         this.mapyPanoramaWrapper.reset();
    135     },
    136 
    137     getState: function () {
    138         const coords = this.mapyPanoramaWrapper.getPanoramaCoords();
    139         const pov = this.mapyPanoramaWrapper.getPov();
    140         if (coords === null || pov === null) {
    141             return null;
    142         }
    143         return [
    144             coords.lat.toFixed(6),
    145             coords.lon.toFixed(6),
    146             pov.yaw.toFixed(4),
    147             pov.pitch.toFixed(4),
    148             pov.fov.toFixed(4),
    149         ];
    150     },
    151 
    152     setState: function (state) {
    153         const lat = parseFloat(state[0]);
    154         const lng = parseFloat(state[1]);
    155         const yaw = parseFloat(state[2]);
    156         const pitch = parseFloat(state[3]);
    157         const fov = parseFloat(state[4]);
    158         if (isNaN(lat) || isNaN(lng) || isNaN(yaw) || isNaN(pitch) || isNaN(fov)) {
    159             return false;
    160         }
    161         this.showPano({lat, lon: lng}, {yaw, pitch, fov});
    162         return true;
    163     },
    164 
    165     onPanoramaPositionChanged: function (position) {
    166         this.fire(Events.ImageChange, {latlng: L.latLng(position.lat, position.lon)});
    167     },
    168 
    169     onPanoramaPovChanged: function (pov) {
    170         this.fire(Events.BearingChange, {bearing: (pov.yaw * 180) / Math.PI});
    171         if (this.povChangeTimer !== null) {
    172             clearTimeout(this.povChangeTimer);
    173             this.povChangeTimer = null;
    174         }
    175         this.povChangeTimer = setTimeout(() => {
    176             this.povChangeTimer = null;
    177             this.fire(Events.YawPitchZoomChangeEnd);
    178         }, 120);
    179     },
    180 
    181     invalidateSize: function () {
    182         // no action needed
    183     },
    184 });
    185 
    186 async function getViewer(container) {
    187     const mapyPanorama = await getPanorama();
    188     return new Viewer(mapyPanorama, container);
    189 }
    190 
    191 const mapyczProvider = {getCoverageLayer, getPanoramaAtPos, getViewer};
    192 export default mapyczProvider;