nakarte

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

layers.js (53941B)


      1 import L from "leaflet";
      2 import '~/lib/leaflet.layer.yandex';
      3 import '~/lib/leaflet.layer.google';
      4 import {BingLayer} 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                     description: 'OSM default style',
     27                     isDefault: true,
     28                     layer: L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png',
     29                         {
     30                             code: 'O',
     31                             isOverlay: false,
     32                             scaleDependent: true,
     33                             print: true,
     34                             jnx: true,
     35                             shortName: 'osm',
     36                             attribution: '<a href="https://www.openstreetmap.org/copyright">' +
     37                                 '&copy; OpenStreetMap contributors</a>',
     38                         }
     39                     )
     40                 },
     41                 {
     42                     title: 'CyclOSM',
     43                     isDefault: true,
     44                     layer: L.tileLayer('https://{s}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png',
     45                         {
     46                             code: 'Co',
     47                             isOverlay: false,
     48                             scaleDependent: true,
     49                             print: true,
     50                             jnx: true,
     51                             shortName: 'cyclosm',
     52                             attribution:
     53                                 '<a href="https://www.openstreetmap.org/copyright">' +
     54                                 '&copy; OpenStreetMap contributors</a>. ' +
     55                                 'Tiles style by <a href="https://www.cyclosm.org/">CyclOSM</a>',
     56                         }
     57                     )
     58                 },
     59                 {
     60                     title: 'ESRI Satellite',
     61                     isDefault: true,
     62                     layer: L.tileLayer(
     63                         'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
     64                         {
     65                             code: 'E',
     66                             isOverlay: false,
     67                             scaleDependent: false,
     68                             maxNativeZoom: 18,
     69                             print: true,
     70                             jnx: true,
     71                             shortName: 'esri',
     72                             attribution:
     73                                 '<a href="https://www.arcgis.com/home/item.html?id=10df2279f9684e4a9f6a7f08febac2a9">' +
     74                                 'ESRI World Imagery for ArcGIS</a>',
     75                         }
     76                     )
     77                 },
     78                 {
     79                     title: 'Yandex map',
     80                     isDefault: true,
     81                     layer: new L.Layer.Yandex.Map(
     82                         {
     83                             scaleDependent: true,
     84                             code: 'Y',
     85                             isOverlay: false,
     86                             print: true,
     87                             jnx: true,
     88                             shortName: 'yandex',
     89                             attribution: '<a href="https://yandex.ru/maps/">Yandex</a>',
     90                         }
     91                     )
     92                 },
     93                 {
     94                     title: 'Yandex Satellite',
     95                     isDefault: true,
     96                     layer: new L.Layer.Yandex.Sat(
     97                         {
     98                             scaleDependent: false,
     99                             code: 'S',
    100                             isOverlay: false,
    101                             print: true,
    102                             jnx: true,
    103                             shortName: 'yandex_sat',
    104                             attribution: '<a href="https://yandex.ru/maps/?l=sat">Yandex</a>',
    105                         }
    106                     )
    107                 },
    108                 {
    109                     title: 'Google Map',
    110                     isDefault: true,
    111                     layer: new L.Layer.GoogleMap(
    112                         {
    113                             code: 'G',
    114                             isOverlay: false,
    115                             scaleDependent: true,
    116                             print: true,
    117                             jnx: true,
    118                             shortName: 'google',
    119                             attribution: '<a href="https://www.google.com/maps">Google</a>',
    120                         }
    121                     )
    122                 },
    123                 {
    124                     title: 'Google Hybrid',
    125                     isDefault: false,
    126                     layer: new L.Layer.GoogleHybrid(
    127                         {
    128                             code: 'Gh',
    129                             isOverlay: true,
    130                             scaleDependent: true,
    131                             print: true,
    132                             jnx: false,
    133                             shortName: 'google_hybrid',
    134                             isOverlayTransparent: true,
    135                             attribution: '<a href="https://www.google.com/maps/@43.0668619,60.5738071,13622628m' +
    136                                 '/data=!3m1!1e3">Google</a>',
    137                         }
    138                     )
    139                 },
    140                 {
    141                     title: 'Google Satellite',
    142                     isDefault: true,
    143                     layer: new L.Layer.GoogleSat(
    144                         {
    145                             code: 'L',
    146                             isOverlay: false,
    147                             scaleDependent: false,
    148                             print: true,
    149                             jnx: true,
    150                             shortName: 'google_sat',
    151                             attribution: '<a href="https://www.google.com/maps/@43.0668619,60.5738071,13622628m' +
    152                                 '/data=!3m1!1e3">Google</a>',
    153                         }
    154                     )
    155                 },
    156                 {
    157                     title: 'Google Terrain',
    158                     isDefault: true,
    159                     layer: new L.Layer.GoogleTerrain({
    160                             code: 'P',
    161                             isOverlay: false,
    162                             scaleDependent: false,
    163                             print: true,
    164                             jnx: true,
    165                             shortName: 'google_terrain',
    166                             attribution: '<a href="https://www.google.com/maps/@43.1203575,42.1105049,9.58z' +
    167                                 '/data=!5m1!1e4">Google</a>',
    168                         }
    169                     )
    170                 },
    171                 {
    172                     title: 'Bing Satellite',
    173                     isDefault: true,
    174                     layer: new BingLayer(config.bingKey,
    175                         {
    176                             code: 'I',
    177                             isOverlay: false,
    178                             scaleDependent: false,
    179                             print: true,
    180                             jnx: true,
    181                             shortName: 'bing_sat'
    182                         }
    183                     )
    184                 },
    185                 {
    186                     title: 'Topomapper 1km',
    187                     isDefault: true,
    188                     layer: L.tileLayer(
    189                         urlViaCorsProxy(
    190                             'http://88.99.52.155/cgi-bin/tapp/tilecache.py/1.0.0/topomapper_v2/{z}/{x}/{y}.jpg'
    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: 9,
    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: 16,
    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                     description: '<a href="https://www.opencyclemap.org/docs/">(Info and key)</a>',
    479                     isDefault: false,
    480                     layer: new RetinaTileLayer(
    481                         [
    482                             'https://{s}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png',
    483                             'https://{s}.tile.thunderforest.com/cycle/{z}/{x}/{y}@2x.png',
    484                         ],
    485                         {
    486                             code: 'Ocm',
    487                             isOverlay: false,
    488                             scaleDependent: true,
    489                             print: true,
    490                             jnx: true,
    491                             shortName: 'opencyclemap',
    492                             attribution: '<a href="https://www.opencyclemap.org/">Thunderforest OpenCycleMap</a>',
    493                         }
    494                     )
    495                 },
    496                 {
    497                     title: 'OSM Outdoors',
    498                     isDefault: false,
    499                     layer: new RetinaTileLayer(
    500                         [
    501                             'https://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png',
    502                             'https://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}@2x.png',
    503                         ],
    504                         {
    505                             code: 'Oso',
    506                             isOverlay: false,
    507                             scaleDependent: true,
    508                             print: true,
    509                             jnx: true,
    510                             shortName: 'osm_outdoors',
    511                             attribution:
    512                                 '<a href="https://www.thunderforest.com/maps/outdoors/">Thunderforest Outdoors</a>',
    513                         }
    514                     )
    515                 },
    516                 {
    517                     title: 'Eurasia 25km',
    518                     description: '1975-80',
    519                     isDefault: false,
    520                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/eurasia25km/{z}/{x}/{y}",
    521                         {
    522                             code: 'E25m',
    523                             isOverlay: true,
    524                             isOverlayTransparent: false,
    525                             tms: true,
    526                             maxNativeZoom: 9,
    527                             print: true,
    528                             jnx: true,
    529                             scaleDependent: false,
    530                             shortName: 'eurasia_25k'
    531                         }
    532                     )
    533                 },
    534                 {
    535                     title: 'Caucasus 1km',
    536                     isDefault: false,
    537                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/new_gsh_100k/{z}/{x}/{y}",
    538                         {
    539                             code: 'NT1',
    540                             isOverlay: true,
    541                             isOverlayTransparent: false,
    542                             tms: true,
    543                             maxNativeZoom: 14,
    544                             print: true,
    545                             jnx: true,
    546                             scaleDependent: false,
    547                             shortName: 'caucasus_1k',
    548                             attribution: '<a href="http://genshtab-yuga.narod.ru/">Topo maps (2006)</a>',
    549                         }
    550                     )
    551                 },
    552                 {
    553                     title: 'Caucasus 500m',
    554                     isDefault: false,
    555                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/new_gsh_050k/{z}/{x}/{y}",
    556                         {
    557                             code: 'NT5',
    558                             isOverlay: true,
    559                             isOverlayTransparent: false,
    560                             tms: true,
    561                             maxNativeZoom: 15,
    562                             print: true,
    563                             jnx: true,
    564                             scaleDependent: false,
    565                             shortName: 'caucasus_500',
    566                             attribution: '<a href="http://genshtab-yuga.narod.ru/">Topo maps (1998 - 2003)</a>',
    567                         }
    568                     )
    569                 },
    570                 {
    571                     title: 'Topo 250m',
    572                     isDefault: false,
    573                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/topo250/{z}/{x}/{y}",
    574                         {
    575                             code: 'T25',
    576                             isOverlay: true,
    577                             isOverlayTransparent: false,
    578                             tms: true,
    579                             maxNativeZoom: 15,
    580                             print: true,
    581                             jnx: true,
    582                             scaleDependent: false,
    583                             shortName: 'topo_250'
    584                         }
    585                     )
    586                 },
    587                 {
    588                     title: 'Montenegro topo 250m',
    589                     description: '1970-72',
    590                     isDefault: false,
    591                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/montenegro250m/{z}/{x}/{y}",
    592                         {
    593                             code: 'MN25',
    594                             isOverlay: true,
    595                             isOverlayTransparent: false,
    596                             tms: true,
    597                             maxNativeZoom: 15,
    598                             print: true,
    599                             jnx: true,
    600                             scaleDependent: false,
    601                             shortName: 'montenegro_250'
    602                         }
    603                     )
    604                 },
    605                 {
    606                     title: 'Mountains by Aleksey Tsvetkov',
    607                     description:
    608                         'Tian Shan, Dzungaria, <a href="http://pereval.g-utka.ru/">http://pereval.g-utka.ru/</a>',
    609                     isDefault: true,
    610                     layer: new LayerGroupWithOptions(
    611                         [
    612                             L.tileLayer(
    613                                 urlViaCorsProxy(
    614                                     'http://nakartetiles.s3-website.eu-central-1.amazonaws.com/{z}/{x}/{y}.png'
    615                                 ),
    616                                 {
    617                                     isOverlay: true,
    618                                     isOverlayTransparent: false,
    619                                     tms: false,
    620                                     minZoom: 2,
    621                                     maxNativeZoom: 15,
    622                                     print: true,
    623                                     jnx: true,
    624                                     scaleDependent: false,
    625                                     noCors: false,
    626                                     shortName: 'tsvetkov_mountains',
    627                                     cutline: getCutline('tsvetkov_mountains'),
    628                                     bounds: [
    629                                         [40.66664, 71.00007],
    630                                         [45.33338, 81.00001],
    631                                     ],
    632                                     attribution: '<a href="http://pereval.g-utka.ru/">Aleksey Tsvetkov</a>',
    633                                 }
    634                             ),
    635                             new LayerCutlineOverview(getCutline('tsvetkov_mountains'), 6,
    636                                 'Mountains by Aleksey Tsvetkov'),
    637                         ],
    638                         {
    639                             code: 'Mt',
    640                             isOverlay: true,
    641                             isWrapper: true,
    642                         }
    643                     ),
    644                 },
    645                 {
    646                     title: 'geocaching.su',
    647                     isDefault: false,
    648                     layer: new GeocachingSu(config.geocachingSuUrl, {
    649                         code: 'Gc',
    650                         isOverlay: true,
    651                         isOverlayTransparent: true,
    652                         print: true,
    653                         jnx: false,
    654                         shortName: 'geocaching',
    655                         attribution: '<a href="https://geocaching.su/">geocaching.su</a>',
    656                     })
    657                 },
    658                 {
    659                     title: 'OpenStreetMap GPS traces',
    660                     isDefault: false,
    661                     layer: L.tileLayer('https://{s}.gps-tile.openstreetmap.org/lines/{z}/{x}/{y}.png',
    662                         {
    663                             code: 'Ot',
    664                             isOverlay: true,
    665                             isOverlayTransparent: true,
    666                             scaleDependent: true,
    667                             print: true,
    668                             jnx: false,
    669                             shortName: 'osm_gps_traces',
    670                             attribution: '<a href="https://www.openstreetmap.org/#&layers=G">' +
    671                                 'OpenStreetMap public GPS traces</a>',
    672                         }
    673                     )
    674                 },
    675                 {
    676                     title: 'Strava heatmap (all)',
    677                     isDefault: false,
    678                     layer: new RetinaTileLayer(
    679                         [
    680                             urlViaCorsProxy(
    681                                 'https://heatmap-external-a.strava.com/tiles-auth/all/hot/{z}/{x}/{y}.png?px=256'
    682                             ),
    683                             urlViaCorsProxy(
    684                                 'https://heatmap-external-a.strava.com/tiles-auth/all/hot/{z}/{x}/{y}.png?px=512'
    685                             ),
    686                         ],
    687                         {
    688                             code: 'Sa',
    689                             isOverlay: true,
    690                             isOverlayTransparent: true,
    691                             scaleDependent: false,
    692                             print: true,
    693                             jnx: false,
    694                             subdomains: 'abc',
    695                             noCors: true,
    696                             shortName: 'strava_all',
    697                             retinaOptionsOverrides: [{maxNativeZoom: 16}, {maxNativeZoom: 15}],
    698                             attribution: '<a href="https://www.strava.com/heatmap">Strava Global Heatmap</a>',
    699                             opacity: 0.75,
    700                         }
    701                     )
    702                 },
    703                 {
    704                     title: 'Strava heatmap (run)',
    705                     isDefault: false,
    706                     layer: new RetinaTileLayer(
    707                         [
    708                             urlViaCorsProxy(
    709                                 'https://heatmap-external-a.strava.com/tiles-auth/run/hot/{z}/{x}/{y}.png?px=256'
    710                             ),
    711                             urlViaCorsProxy(
    712                                 'https://heatmap-external-a.strava.com/tiles-auth/run/hot/{z}/{x}/{y}.png?px=512'
    713                             ),
    714                         ],
    715                         {
    716                             code: 'Sr',
    717                             isOverlay: true,
    718                             isOverlayTransparent: true,
    719                             scaleDependent: false,
    720                             print: true,
    721                             jnx: false,
    722                             subdomains: 'abc',
    723                             noCors: true,
    724                             shortName: 'strava_run',
    725                             retinaOptionsOverrides: [{maxNativeZoom: 16}, {maxNativeZoom: 15}],
    726                             attribution: '<a href="https://www.strava.com/heatmap">Strava Global Heatmap</a>',
    727                             opacity: 0.75,
    728                         }
    729                     )
    730                 },
    731                 {
    732                     title: 'Strava heatmap (ride)',
    733                     isDefault: false,
    734                     layer: new RetinaTileLayer(
    735                         [
    736                             urlViaCorsProxy(
    737                                 'https://heatmap-external-a.strava.com/tiles-auth/ride/hot/{z}/{x}/{y}.png?px=256'
    738                             ),
    739                             urlViaCorsProxy(
    740                                 'https://heatmap-external-a.strava.com/tiles-auth/ride/hot/{z}/{x}/{y}.png?px=512'
    741                             ),
    742                         ],
    743                         {
    744                             code: 'Sb',
    745                             isOverlay: true,
    746                             isOverlayTransparent: true,
    747                             scaleDependent: false,
    748                             print: true,
    749                             jnx: false,
    750                             subdomains: 'abc',
    751                             noCors: true,
    752                             shortName: 'strava_ride',
    753                             retinaOptionsOverrides: [{maxNativeZoom: 16}, {maxNativeZoom: 15}],
    754                             attribution: '<a href="https://www.strava.com/heatmap">Strava Global Heatmap</a>',
    755                             opacity: 0.75,
    756                         }
    757                     )
    758                 },
    759                 {
    760                     title: 'Strava heatmap (winter)',
    761                     isDefault: false,
    762                     layer: new RetinaTileLayer(
    763                         [
    764                             urlViaCorsProxy(
    765                                 'https://heatmap-external-a.strava.com/tiles-auth/winter/hot/{z}/{x}/{y}.png?px=256'
    766                             ),
    767                             urlViaCorsProxy(
    768                                 'https://heatmap-external-a.strava.com/tiles-auth/winter/hot/{z}/{x}/{y}.png?px=512'
    769                             ),
    770                         ],
    771                         {
    772                             code: 'Sw',
    773                             isOverlay: true,
    774                             isOverlayTransparent: true,
    775                             scaleDependent: false,
    776                             print: true,
    777                             jnx: false,
    778                             subdomains: 'abc',
    779                             noCors: true,
    780                             shortName: 'strava_winter',
    781                             retinaOptionsOverrides: [{maxNativeZoom: 16}, {maxNativeZoom: 15}],
    782                             attribution: '<a href="https://www.strava.com/heatmap">Strava Global Heatmap</a>',
    783                             opacity: 0.75,
    784                         }
    785                     )
    786                 },
    787                 {
    788                     title: 'Norway paper map',
    789                     isDefault: false,
    790                     layer: new L.TileLayer(
    791                         'https://opencache.statkart.no/gatekeeper/gk/gk.open_gmaps?layers=toporaster4&zoom={z}&x={x}&y={y}', // eslint-disable-line max-len
    792                         {
    793                             code: 'Np',
    794                             isOverlay: true,
    795                             isOverlayTransparent: false,
    796                             maxNativeZoom: 16,
    797                             tms: false,
    798                             print: true,
    799                             jnx: true,
    800                             scaleDependent: true,
    801                             noCors: false,
    802                             shortName: 'norway_paper',
    803                             bounds: [[57.81324, 4.19674], [71.27961, 31.56094]],
    804                             attribution: '<a href="https://www.geonorge.no/aktuelt/om-geonorge/brukerveiledning' +
    805                                 '/#!#se_paa_kart">Geonorge</a>',
    806                         }
    807                     )
    808                 },
    809                 {
    810                     title: 'Norway topo',
    811                     isDefault: false,
    812                     layer: new L.TileLayer(
    813                         'https://opencache.statkart.no/gatekeeper/gk/gk.open_gmaps?layers=topo4&zoom={z}&x={x}&y={y}',
    814                         {
    815                             code: 'Nm',
    816                             isOverlay: true,
    817                             isOverlayTransparent: false,
    818                             tms: false,
    819                             print: true,
    820                             jnx: true,
    821                             scaleDependent: true,
    822                             noCors: false,
    823                             shortName: 'norway_topo',
    824                             bounds: [[57.81324, 4.19674], [71.27961, 31.56094]],
    825                             attribution: '<a href="https://www.geonorge.no/aktuelt/om-geonorge/brukerveiledning' +
    826                                 '/#!#se_paa_kart">Geonorge</a>',
    827                         }
    828                     )
    829                 },
    830                 {
    831                     // Вместо 404 отдают 500 для отсутствующих тайлов
    832                     title: 'Norway roads',
    833                     description: '<a href="https://kart.finn.no/">https://kart.finn.no/</a>',
    834                     isDefault: false,
    835                     layer: L.tileLayer("https://maptiles1.finncdn.no/tileService/1.0.3/normap/{z}/{x}/{y}.png",
    836                         {
    837                             code: 'Nr',
    838                             isOverlay: true,
    839                             isOverlayTransparent: false,
    840                             tms: false,
    841                             print: true,
    842                             jnx: true,
    843                             scaleDependent: true,
    844                             noCors: false,
    845                             shortName: 'norway_roads',
    846                             bounds: [[57.81324, 4.19674], [71.27961, 31.56094]],
    847                             cutline: getCutline('norway'),
    848                             attribution: '<a href="https://kart.finn.no/">finn.no</a>',
    849                         }
    850                     )
    851                 },
    852                 {
    853                     title: 'mapy.cz tourist',
    854                     isDefault: false,
    855                     layer: new RetinaTileLayer(
    856                         [
    857                             'https://proxy.nakarte.me/mapy/turist-en/{z}-{x}-{y}',
    858                             'https://proxy.nakarte.me/mapy/turist-en/retina/{z}-{x}-{y}',
    859                         ],
    860                         {
    861                             code: 'Czt',
    862                             isOverlay: false,
    863                             tms: false,
    864                             print: true,
    865                             jnx: true,
    866                             scaleDependent: true,
    867                             shortName: 'czech_tourist',
    868                             hotkey: 'H',
    869                             attribution: '<a href="https://mapy.cz/turisticka">mapy.cz outdoor map</a>',
    870                         }
    871                     )
    872                 },
    873                 {
    874                     title: 'Finland Topo',
    875                     description: '<a href="https://laji.fi/en/map/">LAJI.FI</a>',
    876                     isDefault: false,
    877                     layer: L.tileLayer(
    878                         "https://proxy.laji.fi/mml_wmts/maasto/wmts/1.0.0/maastokartta/default/WGS84_Pseudo-Mercator/" +
    879                         "{z}/{y}/{x}.png",
    880                         {
    881                             code: 'Fmk',
    882                             isOverlay: true,
    883                             isOverlayTransparent: false,
    884                             tms: false,
    885                             print: true,
    886                             jnx: true,
    887                             scaleDependent: true,
    888                             noCors: false,
    889                             shortName: 'finland_topo',
    890                             bound: [[59.45416, 19.08321], [70.09211, 31.58671]],
    891                             cutline: getCutline('finland'),
    892                             attribution: '<a href="https://laji.fi/en/map/">LAJI.FI</a>',
    893                         }
    894                     )
    895                 },
    896                 {
    897                     title: 'Great Britain Topo',
    898                     isDefault: false,
    899                     layer: new LayerGroupWithOptions(
    900                         [
    901                             new BingLayer(config.bingKey, {
    902                                 type: 'OrdnanceSurvey',
    903                                 minZoom: 12,
    904                                 maxNativeZoom: 16,
    905                                 bounds: [
    906                                     [49.83793, -7.75643],
    907                                     [60.87164, 1.82356],
    908                                 ],
    909                                 isOverlay: true,
    910                                 isOverlayTransparent: false,
    911                                 scaleDependent: true,
    912                                 print: true,
    913                                 jnx: true,
    914                                 shortName: 'england_topo',
    915                                 cutline: getCutline('great_britain'),
    916                                 attribution: '<a href="https://docs.microsoft.com/en-us/bingmaps/v8-web-control/' +
    917                                     'map-control-api/maptypeid-enumeration">Ordnance Survey</a>',
    918                             }),
    919                             new LayerCutlineOverview(getCutline('great_britain'), 11, 'Great Britain Topo (zoom ≥ 12)'),
    920                         ],
    921                         {
    922                             code: 'Gbt',
    923                             isOverlay: true,
    924                             isWrapper: true,
    925                         }
    926                     ),
    927                 },
    928                 {
    929                     title: 'Waymarked Cycling Trails',
    930                     description:
    931                         '<a href="https://cycling.waymarkedtrails.org/">https://cycling.waymarkedtrails.org</a>',
    932                     isDefault: false,
    933                     layer: L.tileLayer('https://tile.waymarkedtrails.org/cycling/{z}/{x}/{y}.png',
    934                         {
    935                             code: 'Wc',
    936                             isOverlay: true,
    937                             tms: false,
    938                             print: true,
    939                             jnx: false,
    940                             scaleDependent: true,
    941                             shortName: 'cycling_trails',
    942                             isOverlayTransparent: true,
    943                             attribution: '<a href="https://cycling.waymarkedtrails.org/">Waymarked Cycling Trails</a>',
    944                         })
    945                 },
    946                 {
    947                     title: 'Waymarked Hiking Trails',
    948                     description: '<a href="https://hiking.waymarkedtrails.org/">https://hiking.waymarkedtrails.org</a>',
    949                     isDefault: false,
    950                     layer: L.tileLayer('https://tile.waymarkedtrails.org/hiking/{z}/{x}/{y}.png',
    951                         {
    952                             code: 'Wh',
    953                             isOverlay: true,
    954                             tms: false,
    955                             print: true,
    956                             jnx: false,
    957                             scaleDependent: true,
    958                             shortName: 'hiking_trails',
    959                             isOverlayTransparent: true,
    960                             attribution: '<a href="https://hiking.waymarkedtrails.org/">Waymarked Hiking Trails</a>',
    961                         })
    962                 },
    963                 {
    964                     title: 'Slovakia topo',
    965                     description: '<a href="https://mapy.hiking.sk">https://mapy.hiking.sk/</a>',
    966                     isDefault: false,
    967                     layer: new LayerGroupWithOptions(
    968                         [
    969                             L.tileLayer('https://static.mapy.hiking.sk/topo/{z}/{x}/{y}.png', {
    970                                 isOverlay: true,
    971                                 tms: false,
    972                                 print: true,
    973                                 jnx: true,
    974                                 scaleDependent: true,
    975                                 shortName: 'slovakia_topo',
    976                                 isOverlayTransparent: false,
    977                                 maxNativeZoom: 15,
    978                                 minZoom: 10,
    979                                 bounds: [
    980                                     [47.5172, 16.74316],
    981                                     [49.91343, 22.74837],
    982                                 ],
    983                                 noCors: true,
    984                                 cutline: getCutline('slovakia'),
    985                                 attribution: '<a href="https://mapy.hiking.sk/">mapy.hiking.sk</a>',
    986                             }),
    987                             new LayerCutlineOverview(getCutline('slovakia'), 9, 'Slovakia topo (zoom ≥ 10)'),
    988                         ],
    989                         {
    990                             code: 'St',
    991                             isOverlay: true,
    992                             isWrapper: true,
    993                         }
    994                     ),
    995                 },
    996                 {
    997                     title: 'Spain topo',
    998                     isDefault: false,
    999                     layer: L.tileLayer(
   1000                             'https://www.ign.es/wmts/mapa-raster?layer=MTN&style=default&' +
   1001                             'tilematrixset=GoogleMapsCompatible&Service=WMTS&Request=GetTile&Version=1.0.0&' +
   1002                             'Format=image%2Fjpeg&TileMatrix={z}&TileCol={x}&TileRow={y}',
   1003                             {
   1004                                 code: 'Sp',
   1005                                 isOverlay: true,
   1006                                 tms: false,
   1007                                 print: true,
   1008                                 jnx: true,
   1009                                 scaleDependent: true,
   1010                                 shortName: 'spain_topo',
   1011                                 isOverlayTransparent: false,
   1012                                 bounds: [[35.9024, -9.51828], [43.8375, 4.50439]],
   1013                                 noCors: false,
   1014                                 cutline: getCutline('spain'),
   1015                                 attribution: '<a href="https://www.ign.es/iberpix2/visor/">' +
   1016                                     'IGN (Spain) topographic map</a>'
   1017                             }
   1018                     )
   1019                 },
   1020                 {
   1021                     title: 'Switzerland topo',
   1022                     isDefault: false,
   1023                     layer: new RetinaTileLayer(
   1024                         [
   1025                             null,
   1026                             urlViaCorsProxy(
   1027                                 'https:///wmts10.geo.admin.ch/1.0.0/ch.swisstopo.pixelkarte-farbe/default/current/' +
   1028                                 '3857/{z}/{x}/{y}.jpeg'
   1029                             ),
   1030                         ],
   1031 
   1032                         {
   1033                                 code: 'Si',
   1034                                 isOverlay: true,
   1035                                 tms: false,
   1036                                 print: true,
   1037                                 jnx: true,
   1038                                 scaleDependent: true,
   1039                                 shortName: 'swiss_topo',
   1040                                 isOverlayTransparent: false,
   1041                                 bounds: [[45.80269, 5.87352], [47.86445, 10.6847]],
   1042                                 noCors: false,
   1043                                 maxNativeZoom: 16,
   1044                                 tileSize: 128,
   1045                                 zoomOffset: 1,
   1046                                 cutline: getCutline('switzerland'),
   1047                                 attribution: '<a href="https://map.geo.admin.ch/?topic=swisstopo&lang=en&bgLayer=' +
   1048                                     'ch.swisstopo.pixelkarte-farbe&E=2586000.76&N=1202020.96&zoom=1">Swisstopo'
   1049                             }, true
   1050                     )
   1051                 },
   1052                 {
   1053                     title: 'Mountains by Alexander Purikov',
   1054                     isDefault: false,
   1055                     layer: L.tileLayer("https://{s}.tiles.nakarte.me/purikov/{z}/{x}/{y}",
   1056                         {
   1057                             code: 'Pur',
   1058                             isOverlay: true,
   1059                             isOverlayTransparent: false,
   1060                             tms: true,
   1061                             scaleDependent: false,
   1062                             maxNativeZoom: 14,
   1063                             noCors: false,
   1064                             print: true,
   1065                             jnx: true,
   1066                             shortName: 'purikov_mountains',
   1067                             attribution: '<a href="https://westra.ru/reports/">Alexander Purikov</a>',
   1068                         }
   1069                     )
   1070                 },
   1071     ];
   1072 
   1073     const groupsDefs = [
   1074         {
   1075             title: 'Default layers',
   1076             layers: [
   1077                 'OpenStreetMap',
   1078                 'CyclOSM',
   1079                 'ESRI Satellite',
   1080                 'Yandex map',
   1081                 'Yandex Satellite',
   1082                 'Google Map',
   1083                 'Google Satellite',
   1084                 'Google Terrain',
   1085                 'Bing Satellite',
   1086                 'Topomapper 1km',
   1087                 'Topo 10km',
   1088                 'GGC 2 km',
   1089                 'ArbaletMO',
   1090                 'Mountains by Aleksey Tsvetkov',
   1091                 'Slazav mountains',
   1092                 'GGC 1km',
   1093                 'Topo 1km',
   1094                 'GGC 500m',
   1095                 'Topo 500m',
   1096                 'GGC 250m',
   1097                 'Slazav Moscow region map',
   1098                 'Races',
   1099                 'O-sport',
   1100                 'Soviet topo maps grid',
   1101                 'Wikimapia',
   1102                 'Mountain passes (Westra)'
   1103             ],
   1104         },
   1105         {
   1106             title: 'OpenStreetMap alternatives',
   1107             layers: [
   1108                 'OpenTopoMap',
   1109                 'OpenCycleMap',
   1110                 'OSM Outdoors',
   1111                 'mapy.cz tourist',
   1112 
   1113             ],
   1114         },
   1115         {
   1116             title: 'Topo maps',
   1117             layers: [
   1118                 'Eurasia 25km',
   1119                 'Caucasus 1km',
   1120                 'Caucasus 500m',
   1121                 'Topo 250m',
   1122                 'Montenegro topo 250m',
   1123                 'Finland Topo',
   1124                 'Great Britain Topo',
   1125                 'Slovakia topo',
   1126                 'Spain topo',
   1127                 'Switzerland topo',
   1128             ],
   1129         },
   1130         {
   1131             title: 'Miscellaneous',
   1132             layers: [
   1133                 'Mountains by Alexander Purikov',
   1134                 'Google Hybrid',
   1135                 'geocaching.su'
   1136             ]
   1137         },
   1138         {
   1139             title: 'Routes and traces',
   1140             layers: [
   1141                 'Waymarked Hiking Trails',
   1142                 'Waymarked Cycling Trails',
   1143                 'OpenStreetMap GPS traces',
   1144                 'Strava heatmap (all)',
   1145                 'Strava heatmap (run)',
   1146                 'Strava heatmap (ride)',
   1147                 'Strava heatmap (winter)',
   1148             ],
   1149 
   1150         },
   1151         {
   1152             title: 'Norway <a href="https://www.ut.no/kart/">https://www.ut.no/kart/</a>',
   1153             layers: [
   1154                 'Norway paper map',
   1155                 'Norway topo',
   1156                 'Norway roads'
   1157             ],
   1158 
   1159         },
   1160     ];
   1161 
   1162     const titlesByOrder = [
   1163         // common base layers
   1164         // OSM
   1165         'OpenStreetMap',
   1166         'CyclOSM',
   1167         'OpenTopoMap',
   1168         'OpenCycleMap',
   1169         'OSM Outdoors',
   1170         'mapy.cz tourist',
   1171         // Satellite
   1172         'ESRI Satellite',
   1173         'Yandex Satellite',
   1174         'Google Satellite',
   1175         'Bing Satellite',
   1176         // Commercial maps
   1177         'Yandex map',
   1178         'Google Map',
   1179         'Google Terrain',
   1180         // Topo maps
   1181         'Topomapper 1km',
   1182 
   1183         // local base layers
   1184 
   1185         // map overlays
   1186         '#custom-bottom',
   1187         'Eurasia 25km',
   1188         'Topo 10km',
   1189         'GGC 2 km',
   1190         'ArbaletMO',
   1191         'Norway roads',
   1192         'Norway paper map',
   1193         'Norway topo',
   1194         'Finland Topo',
   1195         'Slovakia topo',
   1196         'Spain topo',
   1197         'Mountains by Alexander Purikov',
   1198         'Mountains by Aleksey Tsvetkov',
   1199         'Slazav mountains',
   1200         'GGC 1km',
   1201         'Topo 1km',
   1202         'Caucasus 1km',
   1203         'Great Britain Topo',
   1204         'GGC 500m',
   1205         'Topo 500m',
   1206         'Caucasus 500m',
   1207         'GGC 250m',
   1208         'Topo 250m',
   1209         'Montenegro topo 250m',
   1210         'Switzerland topo',
   1211         'Slazav Moscow region map',
   1212         'Races',
   1213         'O-sport',
   1214         '#custom-top',
   1215 
   1216         // line overlays
   1217         'Google Hybrid',
   1218         'Waymarked Hiking Trails',
   1219         'Waymarked Cycling Trails',
   1220         'OpenStreetMap GPS traces',
   1221         'Strava heatmap (all)',
   1222         'Strava heatmap (run)',
   1223         'Strava heatmap (ride)',
   1224         'Strava heatmap (winter)',
   1225         'Soviet topo maps grid',
   1226         'Wikimapia',
   1227 
   1228         // point overlays
   1229         'Mountain passes (Westra)',
   1230         'geocaching.su',
   1231     ];
   1232 
   1233 function getLayers() {
   1234     // set metadata
   1235     for (let layer of layersDefs) {
   1236         layer.layer.meta = {title: layer.title};
   1237     }
   1238 
   1239     // assign order to layers
   1240     const orderByTitle = {};
   1241     for (let i = 0; i < titlesByOrder.length; i++) {
   1242         let title = titlesByOrder[i];
   1243         orderByTitle[title] = i + 1;
   1244     }
   1245 
   1246     for (let layer of layersDefs) {
   1247         const title = layer.title;
   1248         layer.order = orderByTitle[title];
   1249         if (!layer.order) {
   1250             throw new Error(`Layer title not found in titlesByOrder list: ${title}`);
   1251         }
   1252     }
   1253 
   1254     // divide layers by groups
   1255     const grouppedLayers = [];
   1256     const layersByTitle = {};
   1257     for (let layer of layersDefs) {
   1258         layersByTitle[layer.title] = layer;
   1259     }
   1260     for (let groupDef of groupsDefs) {
   1261         let group = {group: groupDef.title, layers: []};
   1262         grouppedLayers.push(group);
   1263         for (let title of groupDef.layers) {
   1264             let layer = layersByTitle[title];
   1265             group.layers.push(layer);
   1266         }
   1267     }
   1268 
   1269     return {
   1270         layers: grouppedLayers,
   1271         customLayersOrder: {
   1272             top: orderByTitle['#custom-top'],
   1273             bottom: orderByTitle['#custom-bottom'],
   1274 
   1275         }
   1276     };
   1277 }
   1278 
   1279 export {getLayers, layersDefs, groupsDefs, titlesByOrder};