nakarte

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

layers.js (58656B)


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