nakarte

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

layers.js (55528B)


      1 import L from "leaflet";
      2 import '~/lib/leaflet.layer.yandex';
      3 import '~/lib/leaflet.layer.google';
      4 import {BingSatLayer, BingOrdnanceSurveyLayer} from '~/lib/leaflet.layer.bing';
      5 import config from './config';
      6 import '~/lib/leaflet.layer.soviet-topomaps-grid';
      7 import '~/lib/leaflet.layer.westraPasses';
      8 import '~/lib/leaflet.layer.wikimapia';
      9 import {GeocachingSu} from '~/lib/leaflet.layer.geocaching-su';
     10 import {RetinaTileLayer} from '~/lib/leaflet.layer.RetinaTileLayer';
     11 import {urlViaCorsProxy} from '~/lib/CORSProxy';
     12 import '~/lib/leaflet.layer.TileLayer.cutline';
     13 import {getCutline} from '~/lib/layers-cutlines';
     14 import {LayerCutlineOverview} from '~/lib/leaflet.layer.LayerCutlineOverview';
     15 
     16 class LayerGroupWithOptions extends L.LayerGroup {
     17     constructor(layers, options) {
     18         super(layers);
     19         L.setOptions(this, options);
     20     }
     21 }
     22 
     23     const layersDefs = [
     24                 {
     25                     title: 'OpenStreetMap',
     26                     isDefault: true,
     27                     layer: L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png',
     28                         {
     29                             code: 'O',
     30                             isOverlay: false,
     31                             scaleDependent: true,
     32                             print: true,
     33                             jnx: true,
     34                             shortName: 'osm',
     35                             attribution: '<a href="https://www.openstreetmap.org/copyright">' +
     36                                 '&copy; OpenStreetMap contributors</a>',
     37                         }
     38                     )
     39                 },
     40                 {
     41                     title: 'CyclOSM',
     42                     isDefault: true,
     43                     layer: L.tileLayer('https://{s}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png',
     44                         {
     45                             code: 'Co',
     46                             isOverlay: false,
     47                             scaleDependent: true,
     48                             print: true,
     49                             jnx: true,
     50                             shortName: 'cyclosm',
     51                             attribution:
     52                                 '<a href="https://www.openstreetmap.org/copyright">' +
     53                                 '&copy; OpenStreetMap contributors</a>. ' +
     54                                 'Tiles style by <a href="https://www.cyclosm.org/">CyclOSM</a>',
     55                         }
     56                     )
     57                 },
     58                 {
     59                     title: 'ESRI Satellite',
     60                     isDefault: true,
     61                     layer: L.tileLayer(
     62                         'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
     63                         {
     64                             code: 'E',
     65                             isOverlay: false,
     66                             scaleDependent: false,
     67                             maxNativeZoom: 18,
     68                             print: true,
     69                             jnx: true,
     70                             shortName: 'esri',
     71                             attribution:
     72                                 '<a href="https://www.arcgis.com/home/item.html?id=10df2279f9684e4a9f6a7f08febac2a9">' +
     73                                 'ESRI World Imagery for ArcGIS</a>',
     74                         }
     75                     )
     76                 },
     77                 {
     78                     title: 'Yandex map',
     79                     isDefault: true,
     80                     layer: new L.Layer.Yandex.Map(
     81                         {
     82                             scaleDependent: true,
     83                             code: 'Y',
     84                             isOverlay: false,
     85                             print: true,
     86                             jnx: true,
     87                             shortName: 'yandex',
     88                             attribution: '<a href="https://yandex.ru/maps/">Yandex</a>',
     89                         }
     90                     )
     91                 },
     92                 {
     93                     title: 'Yandex Satellite',
     94                     isDefault: true,
     95                     layer: new L.Layer.Yandex.Sat(
     96                         {
     97                             scaleDependent: false,
     98                             code: 'S',
     99                             isOverlay: false,
    100                             print: true,
    101                             jnx: true,
    102                             shortName: 'yandex_sat',
    103                             attribution: '<a href="https://yandex.ru/maps/?l=sat">Yandex</a>',
    104                         }
    105                     )
    106                 },
    107                 {
    108                     title: 'Google Map',
    109                     isDefault: true,
    110                     layer: new L.Layer.GoogleMap(
    111                         {
    112                             code: 'G',
    113                             isOverlay: false,
    114                             scaleDependent: true,
    115                             print: true,
    116                             jnx: true,
    117                             shortName: 'google',
    118                             attribution: '<a href="https://www.google.com/maps">Google</a>',
    119                         }
    120                     )
    121                 },
    122                 {
    123                     title: 'Google Hybrid',
    124                     isDefault: false,
    125                     layer: new L.Layer.GoogleHybrid(
    126                         {
    127                             code: 'Gh',
    128                             isOverlay: true,
    129                             scaleDependent: true,
    130                             print: true,
    131                             jnx: false,
    132                             shortName: 'google_hybrid',
    133                             isOverlayTransparent: true,
    134                             attribution: '<a href="https://www.google.com/maps/@43.0668619,60.5738071,13622628m' +
    135                                 '/data=!3m1!1e3">Google</a>',
    136                         }
    137                     )
    138                 },
    139                 {
    140                     title: 'Google Satellite',
    141                     isDefault: true,
    142                     layer: new L.Layer.GoogleSat(
    143                         {
    144                             code: 'L',
    145                             isOverlay: false,
    146                             scaleDependent: false,
    147                             print: true,
    148                             jnx: true,
    149                             shortName: 'google_sat',
    150                             attribution: '<a href="https://www.google.com/maps/@43.0668619,60.5738071,13622628m' +
    151                                 '/data=!3m1!1e3">Google</a>',
    152                         }
    153                     )
    154                 },
    155                 {
    156                     title: 'Google Terrain',
    157                     isDefault: true,
    158                     layer: new L.Layer.GoogleTerrain({
    159                             code: 'P',
    160                             isOverlay: false,
    161                             scaleDependent: false,
    162                             print: true,
    163                             jnx: true,
    164                             shortName: 'google_terrain',
    165                             attribution: '<a href="https://www.google.com/maps/@43.1203575,42.1105049,9.58z' +
    166                                 '/data=!5m1!1e4">Google</a>',
    167                         }
    168                     )
    169                 },
    170                 {
    171                     title: 'Bing Satellite',
    172                     isDefault: true,
    173                     layer: new BingSatLayer(
    174                         {
    175                             code: 'I',
    176                             isOverlay: false,
    177                             scaleDependent: false,
    178                             print: true,
    179                             jnx: true,
    180                             shortName: 'bing_sat',
    181                             attribution: '<a href="https://www.bing.com/maps?style=h">Microsoft</a>',
    182                         }
    183                     )
    184                 },
    185                 {
    186                     title: 'Topomapper 1km',
    187                     isDefault: true,
    188                     layer: L.tileLayer(
    189                         urlViaCorsProxy(
    190                             'http://88.99.52.156/tmg/{z}/{x}/{y}'
    191                         ),
    192                         {
    193                             code: 'T',
    194                             isOverlay: false,
    195                             scaleDependent: false,
    196                             maxNativeZoom: 13,
    197                             noCors: false,
    198                             print: true,
    199                             jnx: true,
    200                             shortName: 'topomapper_1k',
    201                             attribution: '<a href="https://play.google.com/store/apps/' +
    202                                 'details?id=com.atlogis.sovietmaps.free&hl=en&gl=US">Russian Topo Maps</a>',
    203                         }
    204                     )
    205                 },
    206 
    207                 {
    208                     title: 'Topo 10km',
    209                     isDefault: true,
    210                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/topo001m/{z}/{x}/{y}",
    211                         {
    212                             code: 'D',
    213                             isOverlay: true,
    214                             isOverlayTransparent: false,
    215                             tms: true,
    216                             scaleDependent: false,
    217                             maxNativeZoom: 10,
    218                             print: true,
    219                             jnx: true,
    220                             shortName: 'topo_10k'
    221                         }
    222                     )
    223                 },
    224                 {
    225                     title: 'GGC 2 km',
    226                     isDefault: true,
    227                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/ggc2000/{z}/{x}/{y}",
    228                         {
    229                             code: 'N',
    230                             isOverlay: true,
    231                             isOverlayTransparent: false,
    232                             tms: true,
    233                             scaleDependent: false,
    234                             maxNativeZoom: 12,
    235                             print: true,
    236                             jnx: true,
    237                             shortName: 'ggc_2k'
    238                         }
    239                     )
    240                 },
    241                 {
    242                     title: 'ArbaletMO',
    243                     isDefault: true,
    244                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/ArbaletMO/{z}/{x}/{y}",
    245                         {
    246                             code: 'A',
    247                             isOverlay: true,
    248                             isOverlayTransparent: false,
    249                             tms: true,
    250                             scaleDependent: false,
    251                             maxNativeZoom: 13,
    252                             print: true,
    253                             jnx: true,
    254                             shortName: 'arbalet',
    255                             attribution:
    256                                 '<a href="http://www.velozona.ru/forums/showmessage.php?id=3370">Arbalet (2004)</a>',
    257                         }
    258                     )
    259                 },
    260                 {
    261                     title: 'Slazav mountains',
    262                     isDefault: true,
    263                     layer: L.tileLayer("https://slazav.xyz/tiles/hr/{x}-{y}-{z}.png",
    264                         {
    265                             code: 'Q',
    266                             isOverlay: true,
    267                             isOverlayTransparent: false,
    268                             tms: false,
    269                             scaleDependent: false,
    270                             maxNativeZoom: 13,
    271                             noCors: true,
    272                             print: true,
    273                             jnx: true,
    274                             shortName: 'slazav_mountains',
    275                             attribution: '<a href="http://slazav.xyz/maps">Vladislav Zavjalov</a>',
    276                         }
    277                     )
    278                 },
    279                 {
    280                     title: 'GGC 1km',
    281                     isDefault: true,
    282                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/ggc1000/{z}/{x}/{y}",
    283                         {
    284                             code: 'J',
    285                             isOverlay: true,
    286                             isOverlayTransparent: false,
    287                             tms: true,
    288                             scaleDependent: false,
    289                             maxNativeZoom: 13,
    290                             print: true,
    291                             jnx: true,
    292                             shortName: 'ggc_1k'
    293                         }
    294                     )
    295                 },
    296                 {
    297                     title: 'Topo 1km',
    298                     isDefault: true,
    299                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/topo1000/{z}/{x}/{y}",
    300                         {
    301                             code: 'C',
    302                             isOverlay: true,
    303                             isOverlayTransparent: false,
    304                             tms: true,
    305                             scaleDependent: false,
    306                             maxNativeZoom: 13,
    307                             print: true,
    308                             jnx: true,
    309                             shortName: 'topo_1k'
    310                         }
    311                     )
    312                 },
    313                 {
    314                     title: 'GGC 500m',
    315                     isDefault: true,
    316                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/ggc500/{z}/{x}/{y}",
    317                         {
    318                             code: 'F',
    319                             isOverlay: true,
    320                             isOverlayTransparent: false,
    321                             tms: true,
    322                             scaleDependent: false,
    323                             maxNativeZoom: 14,
    324                             print: true,
    325                             jnx: true,
    326                             shortName: 'ggc_500'
    327                         }
    328                     )
    329                 },
    330                 {
    331                     title: 'Topo 500m',
    332                     isDefault: true,
    333                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/topo500/{z}/{x}/{y}",
    334                         {
    335                             code: 'B',
    336                             isOverlay: true,
    337                             isOverlayTransparent: false,
    338                             tms: true,
    339                             scaleDependent: false,
    340                             maxNativeZoom: 14,
    341                             print: true,
    342                             jnx: true,
    343                             shortName: 'topo_500'
    344                         }
    345                     )
    346                 },
    347                 {
    348                     title: 'GGC 250m',
    349                     isDefault: true,
    350                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/ggc250/{z}/{x}/{y}",
    351                         {
    352                             code: 'K',
    353                             isOverlay: true,
    354                             isOverlayTransparent: false,
    355                             tms: true,
    356                             scaleDependent: false,
    357                             maxNativeZoom: 15,
    358                             print: true,
    359                             jnx: true,
    360                             shortName: 'ggc_250'
    361                         }
    362                     )
    363                 },
    364                 {
    365                     title: 'Slazav Moscow region map',
    366                     isDefault: true,
    367                     layer: L.tileLayer("https://slazav.xyz/tiles/podm/{x}-{y}-{z}.png",
    368                         {
    369                             code: 'Z',
    370                             isOverlay: true,
    371                             isOverlayTransparent: false,
    372                             tms: false,
    373                             scaleDependent: false,
    374                             maxNativeZoom: 14,
    375                             noCors: true,
    376                             print: true,
    377                             jnx: true,
    378                             shortName: 'slazav',
    379                             attribution: '<a href="http://slazav.xyz/maps">Vladislav Zavjalov</a>',
    380                         }
    381                     )
    382                 },
    383                 {
    384                     title: 'Races',
    385                     isDefault: true,
    386                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/adraces/{z}/{x}/{y}",
    387                         {
    388                             code: 'U',
    389                             isOverlay: true,
    390                             isOverlayTransparent: false,
    391                             tms: true,
    392                             scaleDependent: false,
    393                             maxNativeZoom: 15,
    394                             print: true,
    395                             jnx: true,
    396                             shortName: 'races'
    397                         }
    398                     )
    399                 },
    400                 {
    401                     title: 'O-sport',
    402                     isDefault: true,
    403                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/osport/{z}/{x}/{y}",
    404                         {
    405                             code: 'R',
    406                             isOverlay: true,
    407                             isOverlayTransparent: false,
    408                             tms: true,
    409                             scaleDependent: false,
    410                             maxNativeZoom: 17,
    411                             print: true,
    412                             jnx: true,
    413                             shortName: 'osport'
    414                         }
    415                     )
    416                 },
    417                 {
    418                     title: 'Soviet topo maps grid',
    419                     isDefault: true,
    420                     layer: new L.Layer.SovietTopoGrid({
    421                         code: 'Ng',
    422                         isOverlay: true,
    423                         print: false,
    424                         jnx: false
    425                     })
    426                 },
    427                 {
    428                     title: 'Wikimapia',
    429                     isDefault: true,
    430                     layer: new L.Wikimapia({
    431                         code: 'W',
    432                         isOverlay: true,
    433                         print: false,
    434                         jnx: false,
    435                         attribution: '<a href="https://wikimapia.org/">Wikimapia</a>',
    436                         tilesBaseUrl: config.wikimapiaTilesBaseUrl,
    437                     })
    438                 },
    439                 {
    440                     title: 'Mountain passes (Westra)',
    441                     isDefault: true,
    442                     layer: new L.Layer.WestraPasses(config.westraDataBaseUrl, {
    443                         code: 'Wp',
    444                         print: true,
    445                         jnx: false,
    446                         scaleDependent: true,
    447                         isOverlay: true,
    448                         isOverlayTransparent: true,
    449                         shortName: 'passes',
    450                         markersOptions: {
    451                             isOverlay: true,
    452                             isOverlayTransparent: true,
    453                             shortName: 'passes'
    454                         },
    455                         attribution: '<a href="http://westra.ru/passes/">Westra passes catalog</a>',
    456                     })
    457                 },
    458                 {
    459                     title: 'OpenTopoMap',
    460                     isDefault: false,
    461                     layer: L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png',
    462                         {
    463                             code: 'Otm',
    464                             isOverlay: false,
    465                             maxNativeZoom: 15,
    466                             scaleDependent: true,
    467                             print: true,
    468                             jnx: true,
    469                             noCors: false,
    470                             shortName: 'opentopo',
    471                             attribution: '<a href="https://opentopomap.org/">OpenTopoMap</a>',
    472                             hotkey: 'V',
    473                         }
    474                     )
    475                 },
    476                 {
    477                     title: 'OpenCycleMap',
    478                     isDefault: false,
    479                     layer: new RetinaTileLayer(
    480                         [
    481                             'https://{s}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png',
    482                             'https://{s}.tile.thunderforest.com/cycle/{z}/{x}/{y}@2x.png',
    483                         ],
    484                         {
    485                             code: 'Ocm',
    486                             isOverlay: false,
    487                             scaleDependent: true,
    488                             print: true,
    489                             jnx: true,
    490                             shortName: 'opencyclemap',
    491                             attribution: '<a href="https://www.opencyclemap.org/">Thunderforest OpenCycleMap</a>',
    492                         }
    493                     )
    494                 },
    495                 {
    496                     title: 'OSM Outdoors',
    497                     isDefault: false,
    498                     layer: new RetinaTileLayer(
    499                         [
    500                             'https://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png',
    501                             'https://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}@2x.png',
    502                         ],
    503                         {
    504                             code: 'Oso',
    505                             isOverlay: false,
    506                             scaleDependent: true,
    507                             print: true,
    508                             jnx: true,
    509                             shortName: 'osm_outdoors',
    510                             attribution:
    511                                 '<a href="https://www.thunderforest.com/maps/outdoors/">Thunderforest Outdoors</a>',
    512                         }
    513                     )
    514                 },
    515                 {
    516                     title: 'Eurasia 25km',
    517                     // description: '1975-80',
    518                     isDefault: false,
    519                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/eurasia25km/{z}/{x}/{y}",
    520                         {
    521                             code: 'E25m',
    522                             isOverlay: true,
    523                             isOverlayTransparent: false,
    524                             tms: true,
    525                             maxNativeZoom: 9,
    526                             print: true,
    527                             jnx: true,
    528                             scaleDependent: false,
    529                             shortName: 'eurasia_25k'
    530                         }
    531                     )
    532                 },
    533                 {
    534                     title: 'Caucasus 1km',
    535                     isDefault: false,
    536                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/new_gsh_100k/{z}/{x}/{y}",
    537                         {
    538                             code: 'NT1',
    539                             isOverlay: true,
    540                             isOverlayTransparent: false,
    541                             tms: true,
    542                             maxNativeZoom: 14,
    543                             print: true,
    544                             jnx: true,
    545                             scaleDependent: false,
    546                             shortName: 'caucasus_1k',
    547                             attribution: '<a href="http://genshtab-yuga.narod.ru/">Topo maps (2006)</a>',
    548                         }
    549                     )
    550                 },
    551                 {
    552                     title: 'Caucasus 500m',
    553                     isDefault: false,
    554                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/new_gsh_050k/{z}/{x}/{y}",
    555                         {
    556                             code: 'NT5',
    557                             isOverlay: true,
    558                             isOverlayTransparent: false,
    559                             tms: true,
    560                             maxNativeZoom: 15,
    561                             print: true,
    562                             jnx: true,
    563                             scaleDependent: false,
    564                             shortName: 'caucasus_500',
    565                             attribution: '<a href="http://genshtab-yuga.narod.ru/">Topo maps (1998 - 2003)</a>',
    566                         }
    567                     )
    568                 },
    569                 {
    570                     title: 'Topo 250m',
    571                     isDefault: false,
    572                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/topo250/{z}/{x}/{y}",
    573                         {
    574                             code: 'T25',
    575                             isOverlay: true,
    576                             isOverlayTransparent: false,
    577                             tms: true,
    578                             maxNativeZoom: 15,
    579                             print: true,
    580                             jnx: true,
    581                             scaleDependent: false,
    582                             shortName: 'topo_250'
    583                         }
    584                     )
    585                 },
    586                 {
    587                     title: 'Montenegro topo 250m',
    588                     // description: '1970-72',
    589                     isDefault: false,
    590                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/montenegro250m/{z}/{x}/{y}",
    591                         {
    592                             code: 'MN25',
    593                             isOverlay: true,
    594                             isOverlayTransparent: false,
    595                             tms: true,
    596                             maxNativeZoom: 15,
    597                             print: true,
    598                             jnx: true,
    599                             scaleDependent: false,
    600                             shortName: 'montenegro_250'
    601                         }
    602                     )
    603                 },
    604                 {
    605                     title: 'Mountains by Aleksey Tsvetkov',
    606                     isDefault: true,
    607                     layer: new LayerGroupWithOptions(
    608                         [
    609                             L.tileLayer(
    610                                 urlViaCorsProxy(
    611                                     'https://maptiles.website.yandexcloud.net/{z}/{x}/{y}.png'
    612                                 ),
    613                                 {
    614                                     isOverlay: true,
    615                                     isOverlayTransparent: false,
    616                                     tms: false,
    617                                     minZoom: 2,
    618                                     maxNativeZoom: 15,
    619                                     print: true,
    620                                     jnx: true,
    621                                     scaleDependent: false,
    622                                     noCors: false,
    623                                     shortName: 'tsvetkov_mountains',
    624                                     cutline: getCutline('tsvetkov_mountains'),
    625                                     bounds: [
    626                                         [40.66664, 71.00007],
    627                                         [45.33338, 81.00001],
    628                                     ],
    629                                     attribution: '<a href="http://pereval.g-utka.ru/">Aleksey Tsvetkov</a>',
    630                                 }
    631                             ),
    632                             new LayerCutlineOverview(getCutline('tsvetkov_mountains'), 6,
    633                                 'Mountains by Aleksey Tsvetkov'),
    634                         ],
    635                         {
    636                             code: 'Mt',
    637                             isOverlay: true,
    638                             isWrapper: true,
    639                         }
    640                     ),
    641                 },
    642                 {
    643                     title: 'geocaching.su',
    644                     isDefault: false,
    645                     layer: new GeocachingSu(config.geocachingSuUrl, {
    646                         code: 'Gc',
    647                         isOverlay: true,
    648                         isOverlayTransparent: true,
    649                         print: true,
    650                         jnx: false,
    651                         shortName: 'geocaching',
    652                         attribution: '<a href="https://geocaching.su/">geocaching.su</a>',
    653                     })
    654                 },
    655                 {
    656                     title: 'OpenStreetMap GPS traces',
    657                     isDefault: false,
    658                     layer: L.tileLayer('https://{s}.gps-tile.openstreetmap.org/lines/{z}/{x}/{y}.png',
    659                         {
    660                             code: 'Ot',
    661                             isOverlay: true,
    662                             isOverlayTransparent: true,
    663                             scaleDependent: true,
    664                             print: true,
    665                             jnx: false,
    666                             shortName: 'osm_gps_traces',
    667                             attribution: '<a href="https://www.openstreetmap.org/#&layers=G">' +
    668                                 'OpenStreetMap public GPS traces</a>',
    669                         }
    670                     )
    671                 },
    672                 {
    673                     title: 'Strava heatmap (all)',
    674                     isDefault: false,
    675                     layer: new RetinaTileLayer(
    676                         [
    677                             urlViaCorsProxy(
    678                                 'https://content-a.strava.com/identified/globalheat/all/hot/{z}/{x}/{y}.png?px=256'
    679                             ),
    680                             urlViaCorsProxy(
    681                                 'https://content-a.strava.com/identified/globalheat/all/hot/{z}/{x}/{y}.png?px=512'
    682                             ),
    683                         ],
    684                         {
    685                             code: 'Sa',
    686                             isOverlay: true,
    687                             isOverlayTransparent: true,
    688                             scaleDependent: false,
    689                             print: true,
    690                             jnx: false,
    691                             subdomains: 'abc',
    692                             noCors: false,
    693                             shortName: 'strava_all',
    694                             retinaOptionsOverrides: [{maxNativeZoom: 16}, {maxNativeZoom: 15}],
    695                             attribution: '<a href="https://www.strava.com/heatmap">Strava Global Heatmap</a>',
    696                             opacity: 0.75,
    697                         }
    698                     )
    699                 },
    700                 {
    701                     title: 'Strava heatmap (run)',
    702                     isDefault: false,
    703                     layer: new RetinaTileLayer(
    704                         [
    705                             urlViaCorsProxy(
    706                                 'https://content-a.strava.com/identified/globalheat/run/hot/{z}/{x}/{y}.png?px=256'
    707                             ),
    708                             urlViaCorsProxy(
    709                                 'https://content-a.strava.com/identified/globalheat/run/hot/{z}/{x}/{y}.png?px=512'
    710                             ),
    711                         ],
    712                         {
    713                             code: 'Sr',
    714                             isOverlay: true,
    715                             isOverlayTransparent: true,
    716                             scaleDependent: false,
    717                             print: true,
    718                             jnx: false,
    719                             subdomains: 'abc',
    720                             noCors: false,
    721                             shortName: 'strava_run',
    722                             retinaOptionsOverrides: [{maxNativeZoom: 16}, {maxNativeZoom: 15}],
    723                             attribution: '<a href="https://www.strava.com/heatmap">Strava Global Heatmap</a>',
    724                             opacity: 0.75,
    725                         }
    726                     )
    727                 },
    728                 {
    729                     title: 'Strava heatmap (ride)',
    730                     isDefault: false,
    731                     layer: new RetinaTileLayer(
    732                         [
    733                             urlViaCorsProxy(
    734                                 'https://content-a.strava.com/identified/globalheat/ride/hot/{z}/{x}/{y}.png?px=256'
    735                             ),
    736                             urlViaCorsProxy(
    737                                 'https://content-a.strava.com/identified/globalheat/ride/hot/{z}/{x}/{y}.png?px=512'
    738                             ),
    739                         ],
    740                         {
    741                             code: 'Sb',
    742                             isOverlay: true,
    743                             isOverlayTransparent: true,
    744                             scaleDependent: false,
    745                             print: true,
    746                             jnx: false,
    747                             subdomains: 'abc',
    748                             noCors: false,
    749                             shortName: 'strava_ride',
    750                             retinaOptionsOverrides: [{maxNativeZoom: 16}, {maxNativeZoom: 15}],
    751                             attribution: '<a href="https://www.strava.com/heatmap">Strava Global Heatmap</a>',
    752                             opacity: 0.75,
    753                         }
    754                     )
    755                 },
    756                 {
    757                     title: 'Strava heatmap (winter)',
    758                     isDefault: false,
    759                     layer: new RetinaTileLayer(
    760                         [
    761                             urlViaCorsProxy(
    762                                 'https://content-a.strava.com/identified/globalheat/winter/hot/{z}/{x}/{y}.png?px=256'
    763                             ),
    764                             urlViaCorsProxy(
    765                                 'https://content-a.strava.com/identified/globalheat/winter/hot/{z}/{x}/{y}.png?px=512'
    766                             ),
    767                         ],
    768                         {
    769                             code: 'Sw',
    770                             isOverlay: true,
    771                             isOverlayTransparent: true,
    772                             scaleDependent: false,
    773                             print: true,
    774                             jnx: false,
    775                             subdomains: 'abc',
    776                             noCors: false,
    777                             shortName: 'strava_winter',
    778                             retinaOptionsOverrides: [{maxNativeZoom: 16}, {maxNativeZoom: 15}],
    779                             attribution: '<a href="https://www.strava.com/heatmap">Strava Global Heatmap</a>',
    780                             opacity: 0.75,
    781                         }
    782                     )
    783                 },
    784                 {
    785                     title: 'Norway paper map',
    786                     isDefault: false,
    787                     layer: new L.TileLayer(
    788                         'https://cache.kartverket.no/v1/wmts/1.0.0/toporaster/default/webmercator/{z}/{y}/{x}.png',
    789                         {
    790                             code: 'Np',
    791                             isOverlay: true,
    792                             isOverlayTransparent: false,
    793                             tms: false,
    794                             print: true,
    795                             jnx: true,
    796                             scaleDependent: true,
    797                             noCors: false,
    798                             shortName: 'norway_paper',
    799                             bounds: [[57.81324, 4.19674], [71.27961, 31.56094]],
    800                             attribution: '<a href="https://kartverket.no/til-lands/kart/turkart">Kartverket</a>',
    801                         }
    802                     )
    803                 },
    804                 {
    805                     title: 'Norway topo',
    806                     isDefault: false,
    807                     layer: new L.TileLayer(
    808                         'https://cache.kartverket.no/v1/wmts/1.0.0/topo/default/webmercator/{z}/{y}/{x}.png',
    809                         {
    810                             code: 'Nm',
    811                             isOverlay: true,
    812                             isOverlayTransparent: false,
    813                             tms: false,
    814                             print: true,
    815                             jnx: true,
    816                             scaleDependent: true,
    817                             noCors: false,
    818                             shortName: 'norway_topo',
    819                             bounds: [[57.81324, 4.19674], [71.27961, 31.56094]],
    820                             attribution: '<a href="https://kartverket.no/til-lands/kart/turkart">Kartverket</a>',
    821                         }
    822                     )
    823                 },
    824                 {
    825                     // Вместо 404 отдают 500 для отсутствующих тайлов
    826                     title: 'Norway roads',
    827                     isDefault: false,
    828                     layer: L.tileLayer("https://maptiles1.finncdn.no/tileService/1.0.3/normap/{z}/{x}/{y}.png",
    829                         {
    830                             code: 'Nr',
    831                             isOverlay: true,
    832                             isOverlayTransparent: false,
    833                             tms: false,
    834                             print: true,
    835                             jnx: true,
    836                             scaleDependent: true,
    837                             noCors: false,
    838                             shortName: 'norway_roads',
    839                             bounds: [[57.81324, 4.19674], [71.27961, 31.56094]],
    840                             cutline: getCutline('norway'),
    841                             attribution: '<a href="https://kart.finn.no/">finn.no</a>',
    842                         }
    843                     )
    844                 },
    845                 {
    846                     title: 'mapy.cz tourist',
    847                     isDefault: true,
    848                     layer: new RetinaTileLayer(
    849                         [
    850                             'https://proxy.nakarte.me/mapy/turist-en/{z}-{x}-{y}',
    851                             'https://proxy.nakarte.me/mapy/turist-en/retina/{z}-{x}-{y}',
    852                         ],
    853                         {
    854                             code: 'Czt',
    855                             isOverlay: false,
    856                             tms: false,
    857                             print: true,
    858                             jnx: true,
    859                             scaleDependent: true,
    860                             shortName: 'czech_tourist',
    861                             hotkey: 'H',
    862                             attribution: '<a href="https://mapy.cz/turisticka">mapy.cz outdoor map</a>',
    863                         }
    864                     )
    865                 },
    866                 {
    867                     title: 'mapy.cz winter',
    868                     isDefault: false,
    869                     layer: new LayerGroupWithOptions([
    870                         new L.TileLayer('https://proxy.nakarte.me/mapy/winter-en-down/{z}-{x}-{y}', {
    871                             tms: false,
    872                             print: true,
    873                             isOverlay: false,
    874                             jnx: true,
    875                             scaleDependent: true,
    876                             shortName: 'czech_winter',
    877                         }),
    878                         new L.TileLayer('https://proxy.nakarte.me/mapy/winter-en-up/{z}-{x}-{y}', {
    879                             tms: false,
    880                             print: true,
    881                             jnx: false,
    882                             isOverlay: true,
    883                             isOverlayTransparent: true,
    884                             scaleDependent: true,
    885                         }),
    886                     ], {
    887                         code: 'Czw',
    888                         isOverlay: false,
    889                         isWrapper: true,
    890                         attribution: '<a href="https://mapy.cz/zimni">mapy.cz winter map</a>',
    891                     }),
    892                 },
    893                 {
    894                     title: 'Finland Topo',
    895                     isDefault: false,
    896                     layer: L.tileLayer(
    897                         "https://proxy.laji.fi/mml_wmts/maasto/wmts/1.0.0/maastokartta/default/WGS84_Pseudo-Mercator/" +
    898                         "{z}/{y}/{x}.png",
    899                         {
    900                             code: 'Fmk',
    901                             isOverlay: true,
    902                             isOverlayTransparent: false,
    903                             tms: false,
    904                             print: true,
    905                             jnx: true,
    906                             scaleDependent: true,
    907                             noCors: false,
    908                             shortName: 'finland_topo',
    909                             bound: [[59.45416, 19.08321], [70.09211, 31.58671]],
    910                             cutline: getCutline('finland'),
    911                             attribution: '<a href="https://laji.fi/en/map/">LAJI.FI</a>',
    912                         }
    913                     )
    914                 },
    915                 {
    916                     title: 'Great Britain Topo',
    917                     isDefault: false,
    918                     layer: new LayerGroupWithOptions(
    919                         [
    920                             new BingOrdnanceSurveyLayer({
    921                                 minZoom: 12,
    922                                 maxNativeZoom: 16,
    923                                 bounds: [
    924                                     [49.83793, -7.75643],
    925                                     [60.87164, 1.82356],
    926                                 ],
    927                                 isOverlay: true,
    928                                 isOverlayTransparent: false,
    929                                 scaleDependent: true,
    930                                 print: true,
    931                                 jnx: true,
    932                                 shortName: 'england_topo',
    933                                 cutline: getCutline('great_britain'),
    934                                 attribution: '<a href="https://docs.microsoft.com/en-us/bingmaps/v8-web-control/' +
    935                                     'map-control-api/maptypeid-enumeration">Ordnance Survey</a>',
    936                             }),
    937                             new LayerCutlineOverview(getCutline('great_britain'), 11, 'Great Britain Topo (zoom ≥ 12)'),
    938                         ],
    939                         {
    940                             code: 'Gbt',
    941                             isOverlay: true,
    942                             isWrapper: true,
    943                         }
    944                     ),
    945                 },
    946                 {
    947                     title: 'Waymarked Cycling Trails',
    948                     isDefault: false,
    949                     layer: L.tileLayer('https://tile.waymarkedtrails.org/cycling/{z}/{x}/{y}.png',
    950                         {
    951                             code: 'Wc',
    952                             isOverlay: true,
    953                             tms: false,
    954                             print: true,
    955                             jnx: false,
    956                             scaleDependent: true,
    957                             shortName: 'cycling_trails',
    958                             isOverlayTransparent: true,
    959                             attribution: '<a href="https://cycling.waymarkedtrails.org/">Waymarked Cycling Trails</a>',
    960                         })
    961                 },
    962                 {
    963                     title: 'Waymarked Hiking Trails',
    964                     isDefault: false,
    965                     layer: L.tileLayer('https://tile.waymarkedtrails.org/hiking/{z}/{x}/{y}.png',
    966                         {
    967                             code: 'Wh',
    968                             isOverlay: true,
    969                             tms: false,
    970                             print: true,
    971                             jnx: false,
    972                             scaleDependent: true,
    973                             shortName: 'hiking_trails',
    974                             isOverlayTransparent: true,
    975                             attribution: '<a href="https://hiking.waymarkedtrails.org/">Waymarked Hiking Trails</a>',
    976                         })
    977                 },
    978                 {
    979                     title: 'Slovakia topo',
    980                     isDefault: false,
    981                     layer: new LayerGroupWithOptions(
    982                         [
    983                             L.tileLayer('https://static.mapy.hiking.sk/topo/{z}/{x}/{y}.png', {
    984                                 isOverlay: true,
    985                                 tms: false,
    986                                 print: true,
    987                                 jnx: true,
    988                                 scaleDependent: true,
    989                                 shortName: 'slovakia_topo',
    990                                 isOverlayTransparent: false,
    991                                 maxNativeZoom: 15,
    992                                 minZoom: 10,
    993                                 bounds: [
    994                                     [47.5172, 16.74316],
    995                                     [49.91343, 22.74837],
    996                                 ],
    997                                 noCors: true,
    998                                 cutline: getCutline('slovakia'),
    999                                 attribution: '<a href="https://mapy.hiking.sk/">mapy.hiking.sk</a>',
   1000                             }),
   1001                             new LayerCutlineOverview(getCutline('slovakia'), 9, 'Slovakia topo (zoom ≥ 10)'),
   1002                         ],
   1003                         {
   1004                             code: 'St',
   1005                             isOverlay: true,
   1006                             isWrapper: true,
   1007                         }
   1008                     ),
   1009                 },
   1010                 {
   1011                     title: 'Spain topo',
   1012                     isDefault: false,
   1013                     layer: L.tileLayer(
   1014                             'https://www.ign.es/wmts/mapa-raster?layer=MTN&style=default&' +
   1015                             'tilematrixset=GoogleMapsCompatible&Service=WMTS&Request=GetTile&Version=1.0.0&' +
   1016                             'Format=image%2Fjpeg&TileMatrix={z}&TileCol={x}&TileRow={y}',
   1017                             {
   1018                                 code: 'Sp',
   1019                                 isOverlay: true,
   1020                                 tms: false,
   1021                                 print: true,
   1022                                 jnx: true,
   1023                                 scaleDependent: true,
   1024                                 shortName: 'spain_topo',
   1025                                 isOverlayTransparent: false,
   1026                                 minZoom: 1,
   1027                                 bounds: [[35.9024, -9.51828], [43.8375, 4.50439]],
   1028                                 noCors: false,
   1029                                 cutline: getCutline('spain'),
   1030                                 attribution: '<a href="https://www.ign.es/iberpix2/visor/">' +
   1031                                     'IGN (Spain) topographic map</a>'
   1032                             }
   1033                     )
   1034                 },
   1035                 {
   1036                     title: 'Switzerland topo',
   1037                     isDefault: false,
   1038                     layer: new RetinaTileLayer(
   1039                         [
   1040                             null,
   1041                             urlViaCorsProxy(
   1042                                 'https:///wmts10.geo.admin.ch/1.0.0/ch.swisstopo.pixelkarte-farbe/default/current/' +
   1043                                 '3857/{z}/{x}/{y}.jpeg'
   1044                             ),
   1045                         ],
   1046 
   1047                         {
   1048                                 code: 'Si',
   1049                                 isOverlay: true,
   1050                                 tms: false,
   1051                                 print: true,
   1052                                 jnx: true,
   1053                                 scaleDependent: true,
   1054                                 shortName: 'swiss_topo',
   1055                                 isOverlayTransparent: false,
   1056                                 bounds: [[45.80269, 5.87352], [47.86445, 10.6847]],
   1057                                 noCors: false,
   1058                                 maxNativeZoom: 16,
   1059                                 tileSize: 128,
   1060                                 zoomOffset: 1,
   1061                                 cutline: getCutline('switzerland'),
   1062                                 attribution: '<a href="https://map.geo.admin.ch/?topic=swisstopo&lang=en&bgLayer=' +
   1063                                     'ch.swisstopo.pixelkarte-farbe&E=2586000.76&N=1202020.96&zoom=1">Swisstopo'
   1064                             }, true
   1065                     )
   1066                 },
   1067                 {
   1068                     title: 'Mountains by Alexander Purikov',
   1069                     isDefault: false,
   1070                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/purikov/{z}/{x}/{y}",
   1071                         {
   1072                             code: 'Pur',
   1073                             isOverlay: true,
   1074                             isOverlayTransparent: false,
   1075                             tms: true,
   1076                             scaleDependent: false,
   1077                             maxNativeZoom: 14,
   1078                             noCors: false,
   1079                             print: true,
   1080                             jnx: true,
   1081                             shortName: 'purikov_mountains',
   1082                             attribution: '<a href="https://westra.ru/reports/">Alexander Purikov</a>',
   1083                         }
   1084                     )
   1085                 },
   1086                 {
   1087                     title: 'Sweden topo',
   1088                     isDefault: false,
   1089                     layer: L.tileLayer(
   1090                         'https://minkarta.lantmateriet.se/map/topowebbcache' +
   1091                         '?layer=topowebb&style=default&tilematrixset=3857&Service=WMTS&Request=GetTile&Version=1.0.0' +
   1092                         '&Format=image%2Fpng&TileMatrix={z}&TileCol={x}&TileRow={y}',
   1093                         {
   1094                             code: 'Se',
   1095                             isOverlay: true,
   1096                             tms: false,
   1097                             print: true,
   1098                             jnx: true,
   1099                             scaleDependent: true,
   1100                             shortName: 'sweden_topo',
   1101                             isOverlayTransparent: false,
   1102                             minZoom: 0,
   1103                             maxNativeZoom: 17,
   1104                             bounds: [[55.13493, 10.58876], [69.07200, 24.18365]],
   1105                             noCors: false,
   1106                             cutline: getCutline('sweden'),
   1107                             attribution: '<a href="https://minkarta.lantmateriet.se/">' +
   1108                                 'Lantmäteriet</a>'
   1109                         }
   1110                     )
   1111                 },
   1112 
   1113     ];
   1114 
   1115     const groupsDefs = [
   1116         {
   1117             title: 'Default layers',
   1118             layers: [
   1119                 'OpenStreetMap',
   1120                 'CyclOSM',
   1121                 'ESRI Satellite',
   1122                 'Yandex map',
   1123                 'Yandex Satellite',
   1124                 'Google Map',
   1125                 'Google Satellite',
   1126                 'Google Terrain',
   1127                 'Bing Satellite',
   1128                 'Topomapper 1km',
   1129                 'Topo 10km',
   1130                 'GGC 2 km',
   1131                 'ArbaletMO',
   1132                 'Mountains by Aleksey Tsvetkov',
   1133                 'Slazav mountains',
   1134                 'GGC 1km',
   1135                 'Topo 1km',
   1136                 'GGC 500m',
   1137                 'Topo 500m',
   1138                 'GGC 250m',
   1139                 'Slazav Moscow region map',
   1140                 'Races',
   1141                 'O-sport',
   1142                 'Soviet topo maps grid',
   1143                 'Wikimapia',
   1144                 'Mountain passes (Westra)'
   1145             ],
   1146         },
   1147         {
   1148             title: 'OpenStreetMap alternatives',
   1149             layers: [
   1150                 'OpenTopoMap',
   1151                 'OpenCycleMap',
   1152                 'OSM Outdoors',
   1153                 'mapy.cz tourist',
   1154                 'mapy.cz winter',
   1155 
   1156             ],
   1157         },
   1158         {
   1159             title: 'Topo maps',
   1160             layers: [
   1161                 'Eurasia 25km',
   1162                 'Caucasus 1km',
   1163                 'Caucasus 500m',
   1164                 'Topo 250m',
   1165                 'Montenegro topo 250m',
   1166                 'Finland Topo',
   1167                 'Sweden topo',
   1168                 'Great Britain Topo',
   1169                 'Slovakia topo',
   1170                 'Spain topo',
   1171                 'Switzerland topo',
   1172             ],
   1173         },
   1174         {
   1175             title: 'Miscellaneous',
   1176             layers: [
   1177                 'Mountains by Alexander Purikov',
   1178                 'Google Hybrid',
   1179                 'geocaching.su'
   1180             ]
   1181         },
   1182         {
   1183             title: 'Routes and traces',
   1184             layers: [
   1185                 'Waymarked Hiking Trails',
   1186                 'Waymarked Cycling Trails',
   1187                 'OpenStreetMap GPS traces',
   1188                 'Strava heatmap (all)',
   1189                 'Strava heatmap (run)',
   1190                 'Strava heatmap (ride)',
   1191                 'Strava heatmap (winter)',
   1192             ],
   1193 
   1194         },
   1195         {
   1196             title: 'Norway',
   1197             layers: [
   1198                 'Norway paper map',
   1199                 'Norway topo',
   1200                 'Norway roads'
   1201             ],
   1202 
   1203         },
   1204     ];
   1205 
   1206     const titlesByOrder = [
   1207         // common base layers
   1208         // OSM
   1209         'OpenStreetMap',
   1210         'CyclOSM',
   1211         'OpenTopoMap',
   1212         'OpenCycleMap',
   1213         'OSM Outdoors',
   1214         'mapy.cz tourist',
   1215         'mapy.cz winter',
   1216         // Satellite
   1217         'ESRI Satellite',
   1218         'Yandex Satellite',
   1219         'Google Satellite',
   1220         'Bing Satellite',
   1221         // Commercial maps
   1222         'Yandex map',
   1223         'Google Map',
   1224         'Google Terrain',
   1225         // Topo maps
   1226         'Topomapper 1km',
   1227 
   1228         // local base layers
   1229 
   1230         // map overlays
   1231         '#custom-bottom',
   1232         'Eurasia 25km',
   1233         'Topo 10km',
   1234         'GGC 2 km',
   1235         'ArbaletMO',
   1236         'Norway roads',
   1237         'Norway paper map',
   1238         'Norway topo',
   1239         'Finland Topo',
   1240         'Sweden topo',
   1241         'Slovakia topo',
   1242         'Spain topo',
   1243         'Mountains by Alexander Purikov',
   1244         'Mountains by Aleksey Tsvetkov',
   1245         'Slazav mountains',
   1246         'GGC 1km',
   1247         'Topo 1km',
   1248         'Caucasus 1km',
   1249         'Great Britain Topo',
   1250         'GGC 500m',
   1251         'Topo 500m',
   1252         'Caucasus 500m',
   1253         'GGC 250m',
   1254         'Topo 250m',
   1255         'Montenegro topo 250m',
   1256         'Switzerland topo',
   1257         'Slazav Moscow region map',
   1258         'Races',
   1259         'O-sport',
   1260         '#custom-top',
   1261 
   1262         // line overlays
   1263         'Google Hybrid',
   1264         'Waymarked Hiking Trails',
   1265         'Waymarked Cycling Trails',
   1266         'OpenStreetMap GPS traces',
   1267         'Strava heatmap (all)',
   1268         'Strava heatmap (run)',
   1269         'Strava heatmap (ride)',
   1270         'Strava heatmap (winter)',
   1271         'Soviet topo maps grid',
   1272         'Wikimapia',
   1273 
   1274         // point overlays
   1275         'Mountain passes (Westra)',
   1276         'geocaching.su',
   1277     ];
   1278 
   1279 function getLayers() {
   1280     // set metadata
   1281     for (let layer of layersDefs) {
   1282         layer.layer.meta = {title: layer.title};
   1283     }
   1284 
   1285     // assign order to layers
   1286     const orderByTitle = {};
   1287     for (let i = 0; i < titlesByOrder.length; i++) {
   1288         let title = titlesByOrder[i];
   1289         orderByTitle[title] = i + 1;
   1290     }
   1291 
   1292     for (let layer of layersDefs) {
   1293         const title = layer.title;
   1294         layer.order = orderByTitle[title];
   1295         if (!layer.order) {
   1296             throw new Error(`Layer title not found in titlesByOrder list: ${title}`);
   1297         }
   1298     }
   1299 
   1300     // divide layers by groups
   1301     const grouppedLayers = [];
   1302     const layersByTitle = {};
   1303     for (let layer of layersDefs) {
   1304         layersByTitle[layer.title] = layer;
   1305     }
   1306     for (let groupDef of groupsDefs) {
   1307         let group = {group: groupDef.title, layers: []};
   1308         grouppedLayers.push(group);
   1309         for (let title of groupDef.layers) {
   1310             let layer = layersByTitle[title];
   1311             group.layers.push(layer);
   1312         }
   1313     }
   1314 
   1315     return {
   1316         layers: grouppedLayers,
   1317         customLayersOrder: {
   1318             top: orderByTitle['#custom-top'],
   1319             bottom: orderByTitle['#custom-bottom'],
   1320 
   1321         }
   1322     };
   1323 }
   1324 
   1325 export {getLayers, layersDefs, groupsDefs, titlesByOrder};