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