Compare commits
51 Commits
dev
..
b4f96ca777
| Author | SHA1 | Date | |
|---|---|---|---|
| b4f96ca777 | |||
| f8608147e7 | |||
| b95e0fc99c | |||
| 48965d2a95 | |||
| 1f3165f66f | |||
| c08aac3654 | |||
| 824464eda2 | |||
| b0e09b3616 | |||
| b0c5b2b8cf | |||
| 3949369f34 | |||
| 0b4ca57050 | |||
| 68a5937a43 | |||
| 4f725ca01e | |||
| 71eb90fd25 | |||
| 7463f30d1f | |||
| 8ea60d93a1 | |||
| f2aa3de846 | |||
| 21568b0ff9 | |||
| 11a3163f3d | |||
| f70ef1c20d | |||
| 3a8c6c1565 | |||
| df2739807d | |||
| c635a17256 | |||
| e2c3100019 | |||
| b164d5839d | |||
| 6af76a9b6e | |||
| 9ff91480db | |||
| 0d8bf54b42 | |||
| 648f19f217 | |||
| 408686ccba | |||
| d77a01ec22 | |||
| 2da1103853 | |||
| 469d7a5a06 | |||
| 385f07172f | |||
| 2d9dad994b | |||
| 9d25045f15 | |||
| 29feaa48bb | |||
| 80e6f544e4 | |||
| 29d3128a99 | |||
| 02cf5edfda | |||
| 09797f026c | |||
| b4e92a662e | |||
| 33f9b1d0d4 | |||
| 035c411b57 | |||
| 380e968dbc | |||
| 0e0f689b2a | |||
| f7df5873f5 | |||
| da53f62072 | |||
| 7cd320f8f9 | |||
| 897ba92a85 | |||
| 29fb08dd34 |
@@ -70,9 +70,8 @@ This project has been made possible thanks to the following open source projects
|
|||||||
- [SortableJS](https://github.com/SortableJS/Sortable) — creating a sortable file tree
|
- [SortableJS](https://github.com/SortableJS/Sortable) — creating a sortable file tree
|
||||||
- Mapping:
|
- Mapping:
|
||||||
- [MapLibre GL JS](https://github.com/maplibre/maplibre-gl-js) — beautiful and fast interactive map rendering
|
- [MapLibre GL JS](https://github.com/maplibre/maplibre-gl-js) — beautiful and fast interactive map rendering
|
||||||
- [GraphHopper](https://github.com/graphhopper/graphhopper) — powerful routing engine
|
- [GraphHopper](https://github.com/graphhopper/graphhopper) — routing engine
|
||||||
- [OpenStreetMap](https://www.openstreetmap.org) — open map data used by most of the map layers, and by the routing engine
|
- [OpenStreetMap](https://www.openstreetmap.org) — map data used by most of the map layers, and by the routing engine
|
||||||
- [Mapterhorn](https://github.com/mapterhorn/mapterhorn) — high-quality open terrain data used by some map layers (including for 3D), and by the routing engine
|
|
||||||
- Search:
|
- Search:
|
||||||
- [DocSearch](https://github.com/algolia/docsearch) — search engine for the documentation
|
- [DocSearch](https://github.com/algolia/docsearch) — search engine for the documentation
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
"immer": "^10.1.1",
|
"immer": "^10.1.1",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"mapillary-js": "^4.1.2",
|
"mapillary-js": "^4.1.2",
|
||||||
"maplibre-gl": "^6.0.0",
|
"maplibre-gl": "^5.21.1",
|
||||||
"sanitize-html": "^2.17.0",
|
"sanitize-html": "^2.17.0",
|
||||||
"sortablejs": "^1.15.6"
|
"sortablejs": "^1.15.6"
|
||||||
},
|
},
|
||||||
@@ -3236,18 +3236,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mapbox/jsonlint-lines-primitives": {
|
"node_modules/@mapbox/jsonlint-lines-primitives": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.3.tgz",
|
|
||||||
"integrity": "sha512-0SElaV0uMxEnxzBhhX9WTuPyUeMsAN/SS0i16tjuba4/mio63MG9khjC1a0JAiPGXAwvwm4UfHJURCN7nyudQg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 22"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mapbox/point-geometry": {
|
"node_modules/@mapbox/point-geometry": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ==",
|
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/@mapbox/sphericalmercator": {
|
"node_modules/@mapbox/sphericalmercator": {
|
||||||
@@ -3258,32 +3253,24 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@mapbox/tiny-sdf": {
|
"node_modules/@mapbox/tiny-sdf": {
|
||||||
"version": "2.2.0",
|
"version": "2.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.2.0.tgz",
|
|
||||||
"integrity": "sha512-LVL4wgI9YAum5V+LNVQO6QgFBPw7/MIIY4XJPNsPDMrjEwcE+JfKk1LuIl8GnF197ejVdC9QdPaxrx5gfgdGXg==",
|
|
||||||
"license": "BSD-2-Clause"
|
"license": "BSD-2-Clause"
|
||||||
},
|
},
|
||||||
"node_modules/@mapbox/unitbezier": {
|
"node_modules/@mapbox/unitbezier": {
|
||||||
"version": "1.0.0",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-fqd515fjBmANKGGsQ286E2Wvj/XvDFpGzwJxq4CI6jMQue6Oy04uCKp+JWKF00xRTmk6cEu1jPJ9p3xqH8YWqQ==",
|
|
||||||
"license": "BSD-2-Clause"
|
"license": "BSD-2-Clause"
|
||||||
},
|
},
|
||||||
"node_modules/@mapbox/vector-tile": {
|
"node_modules/@mapbox/vector-tile": {
|
||||||
"version": "3.0.0",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@mapbox/vector-tile/-/vector-tile-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-Qf10S1uIHMk20ri/IVBnpS+esUEkVaR5Hftmz88jTInrpmWgPGJfPe3LVjjlE77trLx8tH6qjTG7uWH9hIq/0Q==",
|
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mapbox/point-geometry": "~1.1.0",
|
"@mapbox/point-geometry": "~1.1.0",
|
||||||
"@types/geojson": "^7946.0.16",
|
"@types/geojson": "^7946.0.16",
|
||||||
"pbf": "^5.0.0"
|
"pbf": "^4.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mapbox/vector-tile/node_modules/pbf": {
|
"node_modules/@mapbox/vector-tile/node_modules/pbf": {
|
||||||
"version": "5.1.2",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/pbf/-/pbf-5.1.2.tgz",
|
|
||||||
"integrity": "sha512-mnvGdvOrIvJOBGUEdGkrVXjN8E/VkIJCkf2eS1DH2yv82ORUlLttmDt0rWY38yYZmVwciZwBUvHM20qxBZf40w==",
|
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"resolve-protobuf-schema": "^2.1.0"
|
"resolve-protobuf-schema": "^2.1.0"
|
||||||
@@ -3292,13 +3279,18 @@
|
|||||||
"pbf": "bin/pbf"
|
"pbf": "bin/pbf"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@mapbox/whoots-js": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@maplibre/geojson-vt": {
|
"node_modules/@maplibre/geojson-vt": {
|
||||||
"version": "6.1.1",
|
"version": "6.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@maplibre/geojson-vt/-/geojson-vt-6.1.1.tgz",
|
|
||||||
"integrity": "sha512-FVMOcmSP/yqol45t7StApEyTL5/vmqBCuFhH9n+fFuINenhaX+YgHHIt1yJ86S8kln3uJLcMvmEU2cfn6E2eCQ==",
|
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"kdbush": "^4.1.0"
|
"kdbush": "^4.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@maplibre/maplibre-gl-geocoder": {
|
"node_modules/@maplibre/maplibre-gl-geocoder": {
|
||||||
@@ -3319,16 +3311,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@maplibre/maplibre-gl-style-spec": {
|
"node_modules/@maplibre/maplibre-gl-style-spec": {
|
||||||
"version": "26.2.1",
|
"version": "24.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-26.2.1.tgz",
|
|
||||||
"integrity": "sha512-QFKCXkOeSzOr8jF75jm6kySOg+dUvOehPhRi68gcOYPHb7U5JloUq0dJW0Y5/fZV8ygfT0Vp2RWodvq+fyxFWA==",
|
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mapbox/jsonlint-lines-primitives": "^2.0.3",
|
"@mapbox/jsonlint-lines-primitives": "~2.0.2",
|
||||||
"@mapbox/unitbezier": "^1.0.0",
|
"@mapbox/unitbezier": "^0.0.1",
|
||||||
"json-stringify-pretty-compact": "^4.0.0",
|
"json-stringify-pretty-compact": "^4.0.0",
|
||||||
"minimist": "^1.2.8",
|
"minimist": "^1.2.8",
|
||||||
"quickselect": "^3.0.0",
|
"quickselect": "^3.0.0",
|
||||||
|
"rw": "^1.3.3",
|
||||||
"tinyqueue": "^3.0.0"
|
"tinyqueue": "^3.0.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -3338,29 +3329,31 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@maplibre/mlt": {
|
"node_modules/@maplibre/mlt": {
|
||||||
"version": "1.1.12",
|
"version": "1.1.8",
|
||||||
"resolved": "https://registry.npmjs.org/@maplibre/mlt/-/mlt-1.1.12.tgz",
|
|
||||||
"integrity": "sha512-ZeK5w2TTeHOajcLaEQs1KZXw2V9wIKo1PmThlxlsHoXsQsYlBqLJzPOd6tJHRtGTChUY3DPPmjXRArYVvAbmZw==",
|
|
||||||
"license": "(MIT OR Apache-2.0)",
|
"license": "(MIT OR Apache-2.0)",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mapbox/point-geometry": "^1.1.0"
|
"@mapbox/point-geometry": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@maplibre/vt-pbf": {
|
"node_modules/@maplibre/vt-pbf": {
|
||||||
"version": "4.3.2",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@maplibre/vt-pbf/-/vt-pbf-4.3.2.tgz",
|
|
||||||
"integrity": "sha512-j6p0AdjvAR19Z3XaCysle7A4ZSo08tYOzxD0Y9NQylwPAkwJJeYub5b2eVucdeDh7erhv69DahoLOevDRERRUw==",
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mapbox/point-geometry": "^1.1.0",
|
"@mapbox/point-geometry": "^1.1.0",
|
||||||
|
"@mapbox/vector-tile": "^2.0.4",
|
||||||
|
"@maplibre/geojson-vt": "^5.0.4",
|
||||||
"@types/geojson": "^7946.0.16",
|
"@types/geojson": "^7946.0.16",
|
||||||
"pbf": "^5.1.0"
|
"@types/supercluster": "^7.1.3",
|
||||||
|
"pbf": "^4.0.1",
|
||||||
|
"supercluster": "^8.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@maplibre/vt-pbf/node_modules/@maplibre/geojson-vt": {
|
||||||
|
"version": "5.0.4",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/@maplibre/vt-pbf/node_modules/pbf": {
|
"node_modules/@maplibre/vt-pbf/node_modules/pbf": {
|
||||||
"version": "5.1.2",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/pbf/-/pbf-5.1.2.tgz",
|
|
||||||
"integrity": "sha512-mnvGdvOrIvJOBGUEdGkrVXjN8E/VkIJCkf2eS1DH2yv82ORUlLttmDt0rWY38yYZmVwciZwBUvHM20qxBZf40w==",
|
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"resolve-protobuf-schema": "^2.1.0"
|
"resolve-protobuf-schema": "^2.1.0"
|
||||||
@@ -4296,6 +4289,13 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/supercluster": {
|
||||||
|
"version": "7.1.3",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/geojson": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/three": {
|
"node_modules/@types/three": {
|
||||||
"version": "0.134.0",
|
"version": "0.134.0",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
@@ -5720,8 +5720,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/json-stringify-pretty-compact": {
|
"node_modules/json-stringify-pretty-compact": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==",
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/jszip": {
|
"node_modules/jszip": {
|
||||||
@@ -5735,9 +5733,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/kdbush": {
|
"node_modules/kdbush": {
|
||||||
"version": "4.1.0",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-e9vurzrXJQrFX6ckpHP3bvj5l+9CnYzkxDNnNQ1h2QTqdWsUAJgXiKdGNcOa1EY85dU8KbQ+z/FdQdB7P+9yfQ==",
|
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/keyv": {
|
"node_modules/keyv": {
|
||||||
@@ -6158,25 +6154,25 @@
|
|||||||
"license": "(MIT AND Zlib)"
|
"license": "(MIT AND Zlib)"
|
||||||
},
|
},
|
||||||
"node_modules/maplibre-gl": {
|
"node_modules/maplibre-gl": {
|
||||||
"version": "6.0.0",
|
"version": "5.22.0",
|
||||||
"resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-6.0.0.tgz",
|
|
||||||
"integrity": "sha512-1wBgEhzTZfA+cDpFdt0fM1mJA5mJ90fifORJ7D8JcKLJCvPT/iTx9bNxkP7DqEYde65DJd7gE7h83khwNRqdyg==",
|
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@mapbox/jsonlint-lines-primitives": "^2.0.2",
|
||||||
"@mapbox/point-geometry": "^1.1.0",
|
"@mapbox/point-geometry": "^1.1.0",
|
||||||
"@mapbox/tiny-sdf": "^2.2.0",
|
"@mapbox/tiny-sdf": "^2.0.7",
|
||||||
"@mapbox/unitbezier": "^1.0.0",
|
"@mapbox/unitbezier": "^0.0.1",
|
||||||
"@mapbox/vector-tile": "^3.0.0",
|
"@mapbox/vector-tile": "^2.0.4",
|
||||||
"@maplibre/geojson-vt": "^6.1.1",
|
"@mapbox/whoots-js": "^3.1.0",
|
||||||
"@maplibre/maplibre-gl-style-spec": "^26.1.0",
|
"@maplibre/geojson-vt": "^6.0.4",
|
||||||
"@maplibre/mlt": "^1.1.12",
|
"@maplibre/maplibre-gl-style-spec": "^24.8.1",
|
||||||
"@maplibre/vt-pbf": "^4.3.2",
|
"@maplibre/mlt": "^1.1.8",
|
||||||
|
"@maplibre/vt-pbf": "^4.3.0",
|
||||||
"@types/geojson": "^7946.0.16",
|
"@types/geojson": "^7946.0.16",
|
||||||
"earcut": "^3.2.3",
|
"earcut": "^3.0.2",
|
||||||
"gl-matrix": "^3.4.4",
|
"gl-matrix": "^3.4.4",
|
||||||
"kdbush": "^4.1.0",
|
"kdbush": "^4.0.2",
|
||||||
"murmurhash-js": "^1.0.0",
|
"murmurhash-js": "^1.0.0",
|
||||||
"pbf": "^5.1.2",
|
"pbf": "^4.0.1",
|
||||||
"potpack": "^2.1.0",
|
"potpack": "^2.1.0",
|
||||||
"quickselect": "^3.0.0",
|
"quickselect": "^3.0.0",
|
||||||
"tinyqueue": "^3.0.0"
|
"tinyqueue": "^3.0.0"
|
||||||
@@ -6190,15 +6186,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/maplibre-gl/node_modules/earcut": {
|
"node_modules/maplibre-gl/node_modules/earcut": {
|
||||||
"version": "3.2.3",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/earcut/-/earcut-3.2.3.tgz",
|
|
||||||
"integrity": "sha512-vnS4AVwp1KHAF13i1vp1/2D5evWy3k5u/iW/B81QVsUZtV8cv2tU0b2VNFlqvh4kYwrFMDdjPCfAmfyJW9y14Q==",
|
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/maplibre-gl/node_modules/pbf": {
|
"node_modules/maplibre-gl/node_modules/pbf": {
|
||||||
"version": "5.1.2",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/pbf/-/pbf-5.1.2.tgz",
|
|
||||||
"integrity": "sha512-mnvGdvOrIvJOBGUEdGkrVXjN8E/VkIJCkf2eS1DH2yv82ORUlLttmDt0rWY38yYZmVwciZwBUvHM20qxBZf40w==",
|
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"resolve-protobuf-schema": "^2.1.0"
|
"resolve-protobuf-schema": "^2.1.0"
|
||||||
@@ -6259,8 +6251,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/minimist": {
|
"node_modules/minimist": {
|
||||||
"version": "1.2.8",
|
"version": "1.2.8",
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
|
||||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
@@ -6795,8 +6785,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/quickselect": {
|
"node_modules/quickselect": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==",
|
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/rbush": {
|
"node_modules/rbush": {
|
||||||
@@ -6932,6 +6920,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rw": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
"node_modules/rxjs": {
|
"node_modules/rxjs": {
|
||||||
"version": "7.8.2",
|
"version": "7.8.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
@@ -7165,6 +7157,13 @@
|
|||||||
"xtend": "^4.0.0"
|
"xtend": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/supercluster": {
|
||||||
|
"version": "8.0.1",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"kdbush": "^4.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/supports-color": {
|
"node_modules/supports-color": {
|
||||||
"version": "7.2.0",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||||
@@ -7406,8 +7405,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/tinyqueue": {
|
"node_modules/tinyqueue": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==",
|
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/totalist": {
|
"node_modules/totalist": {
|
||||||
|
|||||||
@@ -75,7 +75,7 @@
|
|||||||
"immer": "^10.1.1",
|
"immer": "^10.1.1",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"mapillary-js": "^4.1.2",
|
"mapillary-js": "^4.1.2",
|
||||||
"maplibre-gl": "^6.0.0",
|
"maplibre-gl": "^5.21.1",
|
||||||
"sanitize-html": "^2.17.0",
|
"sanitize-html": "^2.17.0",
|
||||||
"sortablejs": "^1.15.6"
|
"sortablejs": "^1.15.6"
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 313 KiB After Width: | Height: | Size: 339 KiB |
|
Before Width: | Height: | Size: 729 KiB |
|
Before Width: | Height: | Size: 308 KiB |
|
Before Width: | Height: | Size: 525 KiB After Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 710 KiB After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 2.8 MiB |
|
After Width: | Height: | Size: 348 KiB |
@@ -31,10 +31,10 @@ import bikerouterGravel from './custom/bikerouter-gravel.json';
|
|||||||
export const maptilerKeyPlaceHolder = 'MAPTILER_KEY';
|
export const maptilerKeyPlaceHolder = 'MAPTILER_KEY';
|
||||||
|
|
||||||
export const basemaps: { [key: string]: string | StyleSpecification } = {
|
export const basemaps: { [key: string]: string | StyleSpecification } = {
|
||||||
libertyTopo: 'https://styles.gpx.studio/liberty-topo.json',
|
maptilerStreets: `https://api.maptiler.com/maps/streets-v4/style.json?key=${maptilerKeyPlaceHolder}`,
|
||||||
libertySatellite: 'https://styles.gpx.studio/liberty-satellite.json',
|
maptilerTopo: `https://api.maptiler.com/maps/topo-v4/style.json?key=${maptilerKeyPlaceHolder}`,
|
||||||
osm: 'https://styles.gpx.studio/osm.json',
|
maptilerOutdoors: `https://api.maptiler.com/maps/outdoor-v4/style.json?key=${maptilerKeyPlaceHolder}`,
|
||||||
osmTopo: 'https://styles.gpx.studio/osm-topo.json',
|
maptilerSatellite: `https://api.maptiler.com/maps/hybrid-v4/style.json?key=${maptilerKeyPlaceHolder}`,
|
||||||
esriSatellite: {
|
esriSatellite: {
|
||||||
version: 8,
|
version: 8,
|
||||||
sources: {
|
sources: {
|
||||||
@@ -799,10 +799,10 @@ export type LayerTreeType = { [key: string]: LayerTreeType | boolean };
|
|||||||
export const basemapTree: LayerTreeType = {
|
export const basemapTree: LayerTreeType = {
|
||||||
basemaps: {
|
basemaps: {
|
||||||
world: {
|
world: {
|
||||||
libertyTopo: true,
|
maptilerStreets: true,
|
||||||
libertySatellite: true,
|
maptilerTopo: true,
|
||||||
osm: true,
|
maptilerOutdoors: true,
|
||||||
osmTopo: true,
|
maptilerSatellite: true,
|
||||||
esriSatellite: true,
|
esriSatellite: true,
|
||||||
openStreetMap: true,
|
openStreetMap: true,
|
||||||
openTopoMap: true,
|
openTopoMap: true,
|
||||||
@@ -936,7 +936,7 @@ export const overpassTree: LayerTreeType = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Default basemap used
|
// Default basemap used
|
||||||
export const defaultBasemap = 'libertyTopo';
|
export const defaultBasemap = 'maptilerStreets';
|
||||||
|
|
||||||
// Default overlays used (none)
|
// Default overlays used (none)
|
||||||
export const defaultOverlays: LayerTreeType = {
|
export const defaultOverlays: LayerTreeType = {
|
||||||
@@ -1025,10 +1025,10 @@ export const defaultOverpassQueries: LayerTreeType = {
|
|||||||
export const defaultBasemapTree: LayerTreeType = {
|
export const defaultBasemapTree: LayerTreeType = {
|
||||||
basemaps: {
|
basemaps: {
|
||||||
world: {
|
world: {
|
||||||
libertyTopo: true,
|
maptilerStreets: true,
|
||||||
libertySatellite: true,
|
maptilerTopo: true,
|
||||||
osm: true,
|
maptilerOutdoors: true,
|
||||||
osmTopo: true,
|
maptilerSatellite: true,
|
||||||
esriSatellite: false,
|
esriSatellite: false,
|
||||||
openStreetMap: true,
|
openStreetMap: true,
|
||||||
openTopoMap: true,
|
openTopoMap: true,
|
||||||
@@ -1168,7 +1168,7 @@ export type CustomLayer = {
|
|||||||
maxZoom: number;
|
maxZoom: number;
|
||||||
layerType: 'basemap' | 'overlay';
|
layerType: 'basemap' | 'overlay';
|
||||||
resourceType: 'raster' | 'vector';
|
resourceType: 'raster' | 'vector';
|
||||||
value: string | StyleSpecification;
|
value: string | maplibregl.StyleSpecification;
|
||||||
};
|
};
|
||||||
|
|
||||||
type OverpassQueryData = {
|
type OverpassQueryData = {
|
||||||
@@ -1449,7 +1449,7 @@ export const overpassQueryData: Record<string, OverpassQueryData> = {
|
|||||||
color: 'DarkBlue',
|
color: 'DarkBlue',
|
||||||
},
|
},
|
||||||
tags: {
|
tags: {
|
||||||
railway: ['station', 'halt'],
|
railway: 'station',
|
||||||
},
|
},
|
||||||
symbol: 'Ground Transportation',
|
symbol: 'Ground Transportation',
|
||||||
},
|
},
|
||||||
@@ -1487,11 +1487,14 @@ export const overpassQueryData: Record<string, OverpassQueryData> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const terrainSources: { [key: string]: RasterDEMSourceSpecification } = {
|
export const terrainSources: { [key: string]: RasterDEMSourceSpecification } = {
|
||||||
|
'maptiler-dem': {
|
||||||
|
type: 'raster-dem',
|
||||||
|
url: `https://api.maptiler.com/tiles/terrain-rgb-v2/tiles.json?key=${maptilerKeyPlaceHolder}`,
|
||||||
|
},
|
||||||
mapterhorn: {
|
mapterhorn: {
|
||||||
type: 'raster-dem',
|
type: 'raster-dem',
|
||||||
url: 'https://tiles.gpx.studio/mapterhorn.json',
|
url: 'https://tiles.mapterhorn.com/tilejson.json',
|
||||||
encoding: 'terrarium',
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const defaultTerrainSource = 'mapterhorn';
|
export const defaultTerrainSource = 'maptiler-dem';
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
...others
|
...others
|
||||||
}: {
|
}: {
|
||||||
iconOnly?: boolean;
|
iconOnly?: boolean;
|
||||||
company?: 'gpx.studio' | 'github' | 'crowdin' | 'facebook' | 'reddit';
|
company?: 'gpx.studio' | 'maptiler' | 'github' | 'crowdin' | 'facebook' | 'reddit';
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
} = $props();
|
} = $props();
|
||||||
</script>
|
</script>
|
||||||
@@ -19,6 +19,12 @@
|
|||||||
alt="Logo of gpx.studio."
|
alt="Logo of gpx.studio."
|
||||||
{...others}
|
{...others}
|
||||||
/>
|
/>
|
||||||
|
{:else if company === 'maptiler'}
|
||||||
|
<img
|
||||||
|
src="{base}/maptiler-logo{mode.current === 'dark' ? '-dark' : ''}.svg"
|
||||||
|
alt="Logo of Maptiler."
|
||||||
|
{...others}
|
||||||
|
/>
|
||||||
{:else if company === 'github'}
|
{:else if company === 'github'}
|
||||||
<svg
|
<svg
|
||||||
role="img"
|
role="img"
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import topoMap from '$lib/assets/img/docs/maps/topo.png?enhanced';
|
import maptilerTopoMap from '$lib/assets/img/home/maptiler-topo.png?enhanced';
|
||||||
import waymarkedMap from '$lib/assets/img/docs/maps/waymarked.png?enhanced';
|
import waymarkedMap from '$lib/assets/img/home/waymarked.png?enhanced';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="relative h-80 aspect-square rounded-2xl shadow-xl overflow-clip">
|
<div class="relative h-80 aspect-square rounded-2xl shadow-xl overflow-clip">
|
||||||
<enhanced:img src={topoMap} alt="Topo map screenshot." class="absolute" />
|
<enhanced:img src={maptilerTopoMap} alt="MapTiler Topo map screenshot." class="absolute" />
|
||||||
<enhanced:img
|
<enhanced:img
|
||||||
src={waymarkedMap}
|
src={waymarkedMap}
|
||||||
alt="Waymarked Trails map screenshot."
|
alt="Waymarked Trails map screenshot."
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
import { selection } from '$lib/logic/selection';
|
import { selection } from '$lib/logic/selection';
|
||||||
import { untrack } from 'svelte';
|
import { untrack } from 'svelte';
|
||||||
import { isSelected, toggle } from '$lib/components/map/layer-control/utils';
|
import { isSelected, toggle } from '$lib/components/map/layer-control/utils';
|
||||||
import { boundsManager } from '$lib/logic/bounds';
|
|
||||||
|
|
||||||
let {
|
let {
|
||||||
useHash = true,
|
useHash = true,
|
||||||
@@ -46,6 +45,26 @@
|
|||||||
settings.initialize();
|
settings.initialize();
|
||||||
|
|
||||||
function applyOptions() {
|
function applyOptions() {
|
||||||
|
let downloads: Promise<GPXFile | null>[] = getFilesFromEmbeddingOptions(options).map(
|
||||||
|
(url) => {
|
||||||
|
return fetch(url)
|
||||||
|
.then((response) => response.blob())
|
||||||
|
.then((blob) => new File([blob], url.split('/').pop() ?? url))
|
||||||
|
.then(loadFile);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
Promise.all(downloads).then((answers) => {
|
||||||
|
const files = answers.filter((file) => file !== null) as GPXFile[];
|
||||||
|
let ids: string[] = [];
|
||||||
|
files.forEach((file, index) => {
|
||||||
|
let id = `gpx-${index}-embed`;
|
||||||
|
file._data.id = id;
|
||||||
|
ids.push(id);
|
||||||
|
});
|
||||||
|
fileStateCollection.setEmbeddedFiles(files);
|
||||||
|
$fileOrder = ids;
|
||||||
|
selection.selectAll();
|
||||||
|
});
|
||||||
if (allowedEmbeddingBasemaps.includes(options.basemap)) {
|
if (allowedEmbeddingBasemaps.includes(options.basemap)) {
|
||||||
$currentBasemap = options.basemap;
|
$currentBasemap = options.basemap;
|
||||||
}
|
}
|
||||||
@@ -71,28 +90,6 @@
|
|||||||
].filter((dataset) => dataset !== null)
|
].filter((dataset) => dataset !== null)
|
||||||
);
|
);
|
||||||
elevationFill.set(options.elevation.fill == 'none' ? undefined : options.elevation.fill);
|
elevationFill.set(options.elevation.fill == 'none' ? undefined : options.elevation.fill);
|
||||||
|
|
||||||
let downloads: Promise<GPXFile | null>[] = getFilesFromEmbeddingOptions(options).map(
|
|
||||||
(url) => {
|
|
||||||
return fetch(url)
|
|
||||||
.then((response) => response.blob())
|
|
||||||
.then((blob) => new File([blob], url.split('/').pop() ?? url))
|
|
||||||
.then(loadFile);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
Promise.all(downloads).then((answers) => {
|
|
||||||
const files = answers.filter((file) => file !== null) as GPXFile[];
|
|
||||||
let ids: string[] = [];
|
|
||||||
files.forEach((file, index) => {
|
|
||||||
let id = `gpx-${index}-embed`;
|
|
||||||
file._data.id = id;
|
|
||||||
ids.push(id);
|
|
||||||
});
|
|
||||||
fileStateCollection.setEmbeddedFiles(files);
|
|
||||||
$fileOrder = ids;
|
|
||||||
selection.selectAll();
|
|
||||||
boundsManager.fitBoundsOnLoad(ids);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export const defaultEmbeddingOptions = {
|
|||||||
key: '',
|
key: '',
|
||||||
files: [],
|
files: [],
|
||||||
ids: [],
|
ids: [],
|
||||||
basemap: 'libertyTopo',
|
basemap: 'maptilerStreets',
|
||||||
elevation: {
|
elevation: {
|
||||||
show: true,
|
show: true,
|
||||||
height: 170,
|
height: 170,
|
||||||
@@ -126,7 +126,7 @@ export function convertOldEmbeddingOptions(options: URLSearchParams): any {
|
|||||||
if (options.has('source')) {
|
if (options.has('source')) {
|
||||||
let basemap = options.get('source')!;
|
let basemap = options.get('source')!;
|
||||||
if (basemap === 'satellite') {
|
if (basemap === 'satellite') {
|
||||||
newOptions.basemap = 'libertySatellite';
|
newOptions.basemap = 'maptilerSatellite';
|
||||||
} else if (basemap === 'otm') {
|
} else if (basemap === 'otm') {
|
||||||
newOptions.basemap = 'openTopoMap';
|
newOptions.basemap = 'openTopoMap';
|
||||||
} else if (basemap === 'ohm') {
|
} else if (basemap === 'ohm') {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
import CustomControl from './custom-control';
|
import CustomControl from './custom-control';
|
||||||
import { map } from '$lib/components/map/map';
|
import { map } from '$lib/components/map/map';
|
||||||
import { onMount, type Snippet } from 'svelte';
|
import { onMount, type Snippet } from 'svelte';
|
||||||
import type { Map } from 'maplibre-gl';
|
|
||||||
|
|
||||||
let {
|
let {
|
||||||
position = 'top-right',
|
position = 'top-right',
|
||||||
@@ -18,7 +17,7 @@
|
|||||||
let control: CustomControl | null = null;
|
let control: CustomControl | null = null;
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
map.onLoad((map: Map) => {
|
map.onLoad((map: maplibregl.Map) => {
|
||||||
if (position.includes('right')) container.classList.add('float-right');
|
if (position.includes('right')) container.classList.add('float-right');
|
||||||
else container.classList.add('float-left');
|
else container.classList.add('float-left');
|
||||||
container.classList.remove('hidden');
|
container.classList.remove('hidden');
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ export class DistanceMarkers {
|
|||||||
layout: {
|
layout: {
|
||||||
'text-field': ['get', 'distance'],
|
'text-field': ['get', 'distance'],
|
||||||
'text-size': 14,
|
'text-size': 14,
|
||||||
'text-font': ['Noto Sans Bold'],
|
'text-font': ['Open Sans Bold'],
|
||||||
},
|
},
|
||||||
paint: {
|
paint: {
|
||||||
'text-color': 'black',
|
'text-color': 'black',
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { MapPopup } from '$lib/components/map/map-popup';
|
import { MapPopup } from '$lib/components/map/map-popup';
|
||||||
import type { Map } from 'maplibre-gl';
|
|
||||||
|
|
||||||
export let waypointPopup: MapPopup | null = null;
|
export let waypointPopup: MapPopup | null = null;
|
||||||
export let trackpointPopup: MapPopup | null = null;
|
export let trackpointPopup: MapPopup | null = null;
|
||||||
|
|
||||||
export function createPopups(map: Map) {
|
export function createPopups(map: maplibregl.Map) {
|
||||||
removePopups();
|
removePopups();
|
||||||
waypointPopup = new MapPopup(map, {
|
waypointPopup = new MapPopup(map, {
|
||||||
closeButton: false,
|
closeButton: false,
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { get, type Readable } from 'svelte/store';
|
import { get, type Readable } from 'svelte/store';
|
||||||
import {
|
import maplibregl, {
|
||||||
type GeoJSONSource,
|
type GeoJSONSource,
|
||||||
type FilterSpecification,
|
type FilterSpecification,
|
||||||
type MapLayerMouseEvent,
|
type MapLayerMouseEvent,
|
||||||
type MapLayerTouchEvent,
|
type MapLayerTouchEvent,
|
||||||
Point,
|
|
||||||
} from 'maplibre-gl';
|
} from 'maplibre-gl';
|
||||||
import { map } from '$lib/components/map/map';
|
import { map } from '$lib/components/map/map';
|
||||||
import { waypointPopup, trackpointPopup } from './gpx-layer-popup';
|
import { waypointPopup, trackpointPopup } from './gpx-layer-popup';
|
||||||
@@ -121,7 +120,7 @@ export class GPXLayer {
|
|||||||
selected: boolean = false;
|
selected: boolean = false;
|
||||||
currentWaypointData: GeoJSON.FeatureCollection | null = null;
|
currentWaypointData: GeoJSON.FeatureCollection | null = null;
|
||||||
draggedWaypointIndex: number | null = null;
|
draggedWaypointIndex: number | null = null;
|
||||||
draggingStartingPosition: Point = new Point(0, 0);
|
draggingStartingPosition: maplibregl.Point = new maplibregl.Point(0, 0);
|
||||||
unsubscribe: Function[] = [];
|
unsubscribe: Function[] = [];
|
||||||
|
|
||||||
updateBinded: () => void = this.update.bind(this);
|
updateBinded: () => void = this.update.bind(this);
|
||||||
@@ -252,11 +251,11 @@ export class GPXLayer {
|
|||||||
source: this.fileId,
|
source: this.fileId,
|
||||||
layout: {
|
layout: {
|
||||||
'text-field': '»',
|
'text-field': '»',
|
||||||
'text-offset': [0, -0.1],
|
'text-offset': [0, -0.06],
|
||||||
'text-keep-upright': false,
|
'text-keep-upright': false,
|
||||||
'text-max-angle': 361,
|
'text-max-angle': 361,
|
||||||
'text-allow-overlap': true,
|
'text-allow-overlap': true,
|
||||||
'text-font': ['Noto Sans Bold'],
|
'text-font': ['Open Sans Bold'],
|
||||||
'symbol-placement': 'line',
|
'symbol-placement': 'line',
|
||||||
'symbol-spacing': 20,
|
'symbol-spacing': 20,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
import { Layers } from '@lucide/svelte';
|
import { Layers } from '@lucide/svelte';
|
||||||
import { settings } from '$lib/logic/settings';
|
import { settings } from '$lib/logic/settings';
|
||||||
import { map } from '$lib/components/map/map';
|
import { map } from '$lib/components/map/map';
|
||||||
import type { Map } from 'maplibre-gl';
|
|
||||||
|
|
||||||
let container: HTMLDivElement;
|
let container: HTMLDivElement;
|
||||||
let overpassLayer: OverpassLayer;
|
let overpassLayer: OverpassLayer;
|
||||||
@@ -22,7 +21,7 @@
|
|||||||
selectedOverpassTree,
|
selectedOverpassTree,
|
||||||
} = settings;
|
} = settings;
|
||||||
|
|
||||||
map.onLoad((_map: Map) => {
|
map.onLoad((_map: maplibregl.Map) => {
|
||||||
if (overpassLayer) {
|
if (overpassLayer) {
|
||||||
overpassLayer.remove();
|
overpassLayer.remove();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,7 @@
|
|||||||
poi: PopupItem<any>;
|
poi: PopupItem<any>;
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
let tags: Record<string, string> = $derived(
|
let tags: Record<string, string> = $derived(poi ? JSON.parse(poi.item.tags) : {});
|
||||||
poi ? (typeof poi.item.tags == 'object' ? poi.item.tags : JSON.parse(poi.item.tags)) : {}
|
|
||||||
);
|
|
||||||
let name = $derived.by(() => {
|
let name = $derived.by(() => {
|
||||||
if (poi) {
|
if (poi) {
|
||||||
if (tags.name !== undefined && tags.name !== '') {
|
if (tags.name !== undefined && tags.name !== '') {
|
||||||
@@ -90,14 +88,6 @@
|
|||||||
<span class="font-mono">{key}</span>
|
<span class="font-mono">{key}</span>
|
||||||
{#if key === 'website' || key.startsWith('website:') || key.endsWith(':website') || key === 'contact:facebook' || key === 'contact:instagram' || key === 'contact:twitter'}
|
{#if key === 'website' || key.startsWith('website:') || key.endsWith(':website') || key === 'contact:facebook' || key === 'contact:instagram' || key === 'contact:twitter'}
|
||||||
<a href={value} target="_blank" class="text-link underline">{value}</a>
|
<a href={value} target="_blank" class="text-link underline">{value}</a>
|
||||||
{:else if key === 'wikipedia' || key.startsWith('wikipedia:') || key.endsWith(':wikipedia')}
|
|
||||||
<a
|
|
||||||
href="https://wikipedia.org/wiki/{value}"
|
|
||||||
target="_blank"
|
|
||||||
class="text-link underline"
|
|
||||||
>
|
|
||||||
{value}
|
|
||||||
</a>
|
|
||||||
{:else if key === 'phone' || key === 'contact:phone'}
|
{:else if key === 'phone' || key === 'contact:phone'}
|
||||||
<a href={'tel:' + value} class="text-link underline">{value}</a>
|
<a href={'tel:' + value} class="text-link underline">{value}</a>
|
||||||
{:else if key === 'email' || key === 'contact:email'}
|
{:else if key === 'email' || key === 'contact:email'}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { overpassQueryData } from '$lib/assets/layers';
|
|||||||
import { MapPopup } from '$lib/components/map/map-popup';
|
import { MapPopup } from '$lib/components/map/map-popup';
|
||||||
import { settings } from '$lib/logic/settings';
|
import { settings } from '$lib/logic/settings';
|
||||||
import { db } from '$lib/db';
|
import { db } from '$lib/db';
|
||||||
import type { Map as MapLibreMap, GeoJSONSource } from 'maplibre-gl';
|
import type { GeoJSONSource } from 'maplibre-gl';
|
||||||
import { ANCHOR_LAYER_KEY } from '$lib/components/map/style';
|
import { ANCHOR_LAYER_KEY } from '$lib/components/map/style';
|
||||||
import type { MapLayerEventManager } from '$lib/components/map/map-layer-event-manager';
|
import type { MapLayerEventManager } from '$lib/components/map/map-layer-event-manager';
|
||||||
import { loadSVGIcon } from '$lib/utils';
|
import { loadSVGIcon } from '$lib/utils';
|
||||||
@@ -24,11 +24,11 @@ liveQuery(() => db.overpassdata.toArray()).subscribe((pois) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
export class OverpassLayer {
|
export class OverpassLayer {
|
||||||
overpassUrl = 'https://overpass.gpx.studio/api/interpreter';
|
overpassUrl = 'https://overpass.private.coffee/api/interpreter';
|
||||||
minZoom = 12;
|
minZoom = 12;
|
||||||
queryZoom = 12;
|
queryZoom = 12;
|
||||||
expirationTime = 7 * 24 * 3600 * 1000;
|
expirationTime = 7 * 24 * 3600 * 1000;
|
||||||
map: MapLibreMap;
|
map: maplibregl.Map;
|
||||||
layerEventManager: MapLayerEventManager;
|
layerEventManager: MapLayerEventManager;
|
||||||
popup: MapPopup;
|
popup: MapPopup;
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ export class OverpassLayer {
|
|||||||
updateBinded = this.update.bind(this);
|
updateBinded = this.update.bind(this);
|
||||||
onHoverBinded = this.onHover.bind(this);
|
onHoverBinded = this.onHover.bind(this);
|
||||||
|
|
||||||
constructor(map: MapLibreMap, layerEventManager: MapLayerEventManager) {
|
constructor(map: maplibregl.Map, layerEventManager: MapLayerEventManager) {
|
||||||
this.map = map;
|
this.map = map;
|
||||||
this.layerEventManager = layerEventManager;
|
this.layerEventManager = layerEventManager;
|
||||||
this.popup = new MapPopup(map, {
|
this.popup = new MapPopup(map, {
|
||||||
|
|||||||
@@ -1,19 +1,10 @@
|
|||||||
import { fileStateCollection } from '$lib/logic/file-state';
|
import { fileStateCollection } from '$lib/logic/file-state';
|
||||||
import {
|
import maplibregl from 'maplibre-gl';
|
||||||
LngLatBounds,
|
|
||||||
MapMouseEvent,
|
|
||||||
MapTouchEvent,
|
|
||||||
Point,
|
|
||||||
type Map,
|
|
||||||
type MapGeoJSONFeature,
|
|
||||||
type MapLayerMouseEvent,
|
|
||||||
type MapLayerTouchEvent,
|
|
||||||
} from 'maplibre-gl';
|
|
||||||
|
|
||||||
type MapLayerMouseEventListener = (e: MapLayerMouseEvent) => void;
|
type MapLayerMouseEventListener = (e: maplibregl.MapLayerMouseEvent) => void;
|
||||||
type MapLayerTouchEventListener = (e: MapLayerTouchEvent) => void;
|
type MapLayerTouchEventListener = (e: maplibregl.MapLayerTouchEvent) => void;
|
||||||
type MapLayerListener = {
|
type MapLayerListener = {
|
||||||
features: MapGeoJSONFeature[];
|
features: maplibregl.MapGeoJSONFeature[];
|
||||||
mousemoves: MapLayerMouseEventListener[];
|
mousemoves: MapLayerMouseEventListener[];
|
||||||
mouseenters: MapLayerMouseEventListener[];
|
mouseenters: MapLayerMouseEventListener[];
|
||||||
mouseleaves: MapLayerMouseEventListener[];
|
mouseleaves: MapLayerMouseEventListener[];
|
||||||
@@ -24,10 +15,10 @@ type MapLayerListener = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class MapLayerEventManager {
|
export class MapLayerEventManager {
|
||||||
private _map: Map;
|
private _map: maplibregl.Map;
|
||||||
private _listeners: Record<string, MapLayerListener> = {};
|
private _listeners: Record<string, MapLayerListener> = {};
|
||||||
|
|
||||||
constructor(map: Map) {
|
constructor(map: maplibregl.Map) {
|
||||||
this._map = map;
|
this._map = map;
|
||||||
this._map.on('mousemove', this._handleMouseMove.bind(this));
|
this._map.on('mousemove', this._handleMouseMove.bind(this));
|
||||||
this._map.on('click', this._handleMouseClick.bind(this, 'click'));
|
this._map.on('click', this._handleMouseClick.bind(this, 'click'));
|
||||||
@@ -150,7 +141,7 @@ export class MapLayerEventManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleMouseMove(e: MapMouseEvent) {
|
private _handleMouseMove(e: maplibregl.MapMouseEvent) {
|
||||||
if (e.originalEvent.buttons > 0) return;
|
if (e.originalEvent.buttons > 0) return;
|
||||||
const featuresByLayer = this._getRenderedFeaturesByLayer(e);
|
const featuresByLayer = this._getRenderedFeaturesByLayer(e);
|
||||||
Object.keys(this._listeners).forEach((layerId) => {
|
Object.keys(this._listeners).forEach((layerId) => {
|
||||||
@@ -159,20 +150,29 @@ export class MapLayerEventManager {
|
|||||||
if ((features.length == 0) != (listener.features.length == 0)) {
|
if ((features.length == 0) != (listener.features.length == 0)) {
|
||||||
if (features.length > 0) {
|
if (features.length > 0) {
|
||||||
if (listener.mouseenters.length > 0) {
|
if (listener.mouseenters.length > 0) {
|
||||||
const event = new MapMouseEvent('mouseenter', e.target, e.originalEvent, {
|
const event = new maplibregl.MapMouseEvent(
|
||||||
features: featuresByLayer[layerId]!,
|
'mouseenter',
|
||||||
});
|
e.target,
|
||||||
|
e.originalEvent,
|
||||||
|
{
|
||||||
|
features: featuresByLayer[layerId]!,
|
||||||
|
}
|
||||||
|
);
|
||||||
listener.mouseenters.forEach((l) => l(event));
|
listener.mouseenters.forEach((l) => l(event));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (listener.mouseleaves.length > 0) {
|
if (listener.mouseleaves.length > 0) {
|
||||||
const event = new MapMouseEvent('mouseleave', e.target, e.originalEvent);
|
const event = new maplibregl.MapMouseEvent(
|
||||||
|
'mouseleave',
|
||||||
|
e.target,
|
||||||
|
e.originalEvent
|
||||||
|
);
|
||||||
listener.mouseleaves.forEach((l) => l(event));
|
listener.mouseleaves.forEach((l) => l(event));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (features.length > 0 && listener.mousemoves.length > 0) {
|
if (features.length > 0 && listener.mousemoves.length > 0) {
|
||||||
const event = new MapMouseEvent('mousemove', e.target, e.originalEvent, {
|
const event = new maplibregl.MapMouseEvent('mousemove', e.target, e.originalEvent, {
|
||||||
features: featuresByLayer[layerId]!,
|
features: featuresByLayer[layerId]!,
|
||||||
});
|
});
|
||||||
listener.mousemoves.forEach((l) => l(event));
|
listener.mousemoves.forEach((l) => l(event));
|
||||||
@@ -181,39 +181,49 @@ export class MapLayerEventManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleMouseClick(type: string, e: MapMouseEvent) {
|
private _handleMouseClick(type: string, e: maplibregl.MapMouseEvent) {
|
||||||
const featuresByLayer = this._getRenderedFeaturesByLayer(e);
|
const featuresByLayer = this._getRenderedFeaturesByLayer(e);
|
||||||
Object.keys(this._listeners).forEach((layerId) => {
|
Object.keys(this._listeners).forEach((layerId) => {
|
||||||
const features = featuresByLayer[layerId] || [];
|
const features = featuresByLayer[layerId] || [];
|
||||||
const listener = this._listeners[layerId];
|
const listener = this._listeners[layerId];
|
||||||
if (features.length > 0) {
|
if (features.length > 0) {
|
||||||
if (type === 'click' && listener.clicks.length > 0) {
|
if (type === 'click' && listener.clicks.length > 0) {
|
||||||
const event = new MapMouseEvent('click', e.target, e.originalEvent, {
|
const event = new maplibregl.MapMouseEvent('click', e.target, e.originalEvent, {
|
||||||
features: features,
|
features: features,
|
||||||
});
|
});
|
||||||
listener.clicks.forEach((l) => l(event));
|
listener.clicks.forEach((l) => l(event));
|
||||||
} else if (type === 'contextmenu' && listener.contextmenus.length > 0) {
|
} else if (type === 'contextmenu' && listener.contextmenus.length > 0) {
|
||||||
const event = new MapMouseEvent('contextmenu', e.target, e.originalEvent, {
|
const event = new maplibregl.MapMouseEvent(
|
||||||
features: features,
|
'contextmenu',
|
||||||
});
|
e.target,
|
||||||
|
e.originalEvent,
|
||||||
|
{
|
||||||
|
features: features,
|
||||||
|
}
|
||||||
|
);
|
||||||
listener.contextmenus.forEach((l) => l(event));
|
listener.contextmenus.forEach((l) => l(event));
|
||||||
} else if (type === 'mousedown' && listener.mousedowns.length > 0) {
|
} else if (type === 'mousedown' && listener.mousedowns.length > 0) {
|
||||||
const event = new MapMouseEvent('mousedown', e.target, e.originalEvent, {
|
const event = new maplibregl.MapMouseEvent(
|
||||||
features: features,
|
'mousedown',
|
||||||
});
|
e.target,
|
||||||
|
e.originalEvent,
|
||||||
|
{
|
||||||
|
features: features,
|
||||||
|
}
|
||||||
|
);
|
||||||
listener.mousedowns.forEach((l) => l(event));
|
listener.mousedowns.forEach((l) => l(event));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleTouchStart(e: MapTouchEvent) {
|
private _handleTouchStart(e: maplibregl.MapTouchEvent) {
|
||||||
const featuresByLayer = this._getRenderedFeaturesByLayer(e);
|
const featuresByLayer = this._getRenderedFeaturesByLayer(e);
|
||||||
Object.keys(this._listeners).forEach((layerId) => {
|
Object.keys(this._listeners).forEach((layerId) => {
|
||||||
const features = featuresByLayer[layerId] || [];
|
const features = featuresByLayer[layerId] || [];
|
||||||
const listener = this._listeners[layerId];
|
const listener = this._listeners[layerId];
|
||||||
if (features.length > 0) {
|
if (features.length > 0) {
|
||||||
const event: MapLayerTouchEvent = new MapTouchEvent(
|
const event: maplibregl.MapLayerTouchEvent = new maplibregl.MapTouchEvent(
|
||||||
'touchstart',
|
'touchstart',
|
||||||
e.target,
|
e.target,
|
||||||
e.originalEvent
|
e.originalEvent
|
||||||
@@ -224,15 +234,18 @@ export class MapLayerEventManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getBounds(point: Point) {
|
private _getBounds(point: maplibregl.Point) {
|
||||||
const delta = 30;
|
const delta = 30;
|
||||||
return new LngLatBounds(
|
return new maplibregl.LngLatBounds(
|
||||||
this._map.unproject([point.x - delta, point.y + delta]),
|
this._map.unproject([point.x - delta, point.y + delta]),
|
||||||
this._map.unproject([point.x + delta, point.y - delta])
|
this._map.unproject([point.x + delta, point.y - delta])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _filterLayersIntersectingBounds(layerIds: string[], bounds: LngLatBounds): string[] {
|
private _filterLayersIntersectingBounds(
|
||||||
|
layerIds: string[],
|
||||||
|
bounds: maplibregl.LngLatBounds
|
||||||
|
): string[] {
|
||||||
let result = layerIds.filter((layerId) => {
|
let result = layerIds.filter((layerId) => {
|
||||||
if (!this._map.getLayer(layerId)) return false;
|
if (!this._map.getLayer(layerId)) return false;
|
||||||
const fileId = layerId.replace('-waypoints', '');
|
const fileId = layerId.replace('-waypoints', '');
|
||||||
@@ -248,7 +261,7 @@ export class MapLayerEventManager {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getRenderedFeaturesByLayer(e: MapMouseEvent | MapTouchEvent) {
|
private _getRenderedFeaturesByLayer(e: maplibregl.MapMouseEvent | maplibregl.MapTouchEvent) {
|
||||||
const layerIds = this._filterLayersIntersectingBounds(
|
const layerIds = this._filterLayersIntersectingBounds(
|
||||||
Object.keys(this._listeners),
|
Object.keys(this._listeners),
|
||||||
this._getBounds(e.point)
|
this._getBounds(e.point)
|
||||||
@@ -257,7 +270,7 @@ export class MapLayerEventManager {
|
|||||||
layerIds.length > 0
|
layerIds.length > 0
|
||||||
? this._map.queryRenderedFeatures(e.point, { layers: layerIds })
|
? this._map.queryRenderedFeatures(e.point, { layers: layerIds })
|
||||||
: [];
|
: [];
|
||||||
const featuresByLayer: Record<string, MapGeoJSONFeature[]> = {};
|
const featuresByLayer: Record<string, maplibregl.MapGeoJSONFeature[]> = {};
|
||||||
features.forEach((f) => {
|
features.forEach((f) => {
|
||||||
if (!featuresByLayer[f.layer.id]) {
|
if (!featuresByLayer[f.layer.id]) {
|
||||||
featuresByLayer[f.layer.id] = [];
|
featuresByLayer[f.layer.id] = [];
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { TrackPoint, Waypoint } from 'gpx';
|
import { TrackPoint, Waypoint } from 'gpx';
|
||||||
import { LngLat, Map, MapMouseEvent, Popup, type PopupOptions } from 'maplibre-gl';
|
import maplibregl from 'maplibre-gl';
|
||||||
import { mount, tick, unmount } from 'svelte';
|
import { mount, tick, unmount } from 'svelte';
|
||||||
import { get, writable, type Writable } from 'svelte/store';
|
import { get, writable, type Writable } from 'svelte/store';
|
||||||
import MapPopupComponent from '$lib/components/map/MapPopup.svelte';
|
import MapPopupComponent from '$lib/components/map/MapPopup.svelte';
|
||||||
@@ -11,15 +11,15 @@ export type PopupItem<T = Waypoint | TrackPoint | any> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class MapPopup {
|
export class MapPopup {
|
||||||
map: Map;
|
map: maplibregl.Map;
|
||||||
popup: Popup;
|
popup: maplibregl.Popup;
|
||||||
item: Writable<PopupItem | null> = writable(null);
|
item: Writable<PopupItem | null> = writable(null);
|
||||||
component: ReturnType<typeof mount>;
|
component: ReturnType<typeof mount>;
|
||||||
maybeHideBinded = this.maybeHide.bind(this);
|
maybeHideBinded = this.maybeHide.bind(this);
|
||||||
|
|
||||||
constructor(map: Map, options?: PopupOptions) {
|
constructor(map: maplibregl.Map, options?: maplibregl.PopupOptions) {
|
||||||
this.map = map;
|
this.map = map;
|
||||||
this.popup = new Popup(options);
|
this.popup = new maplibregl.Popup(options);
|
||||||
this.component = mount(MapPopupComponent, {
|
this.component = mount(MapPopupComponent, {
|
||||||
target: document.body,
|
target: document.body,
|
||||||
props: {
|
props: {
|
||||||
@@ -51,7 +51,7 @@ export class MapPopup {
|
|||||||
this.map.on('mousemove', this.maybeHideBinded);
|
this.map.on('mousemove', this.maybeHideBinded);
|
||||||
}
|
}
|
||||||
|
|
||||||
maybeHide(e: MapMouseEvent) {
|
maybeHide(e: maplibregl.MapMouseEvent) {
|
||||||
const item = get(this.item);
|
const item = get(this.item);
|
||||||
if (item === null) {
|
if (item === null) {
|
||||||
this.hide();
|
this.hide();
|
||||||
@@ -75,10 +75,10 @@ export class MapPopup {
|
|||||||
getCoordinates() {
|
getCoordinates() {
|
||||||
const item = get(this.item);
|
const item = get(this.item);
|
||||||
if (item === null) {
|
if (item === null) {
|
||||||
return new LngLat(0, 0);
|
return new maplibregl.LngLat(0, 0);
|
||||||
}
|
}
|
||||||
return item.item instanceof Waypoint || item.item instanceof TrackPoint
|
return item.item instanceof Waypoint || item.item instanceof TrackPoint
|
||||||
? item.item.getCoordinates()
|
? item.item.getCoordinates()
|
||||||
: new LngLat(item.item.lon, item.item.lat);
|
: new maplibregl.LngLat(item.item.lon, item.item.lat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import * as maplibregl from 'maplibre-gl';
|
import maplibregl from 'maplibre-gl';
|
||||||
import 'maplibre-gl/dist/maplibre-gl.css';
|
import 'maplibre-gl/dist/maplibre-gl.css';
|
||||||
import workerUrl from 'maplibre-gl/dist/maplibre-gl-worker.mjs?worker&url';
|
|
||||||
import MaplibreGeocoder, {
|
import MaplibreGeocoder, {
|
||||||
type MaplibreGeocoderFeatureResults,
|
type MaplibreGeocoderFeatureResults,
|
||||||
} from '@maplibre/maplibre-gl-geocoder';
|
} from '@maplibre/maplibre-gl-geocoder';
|
||||||
@@ -40,7 +39,6 @@ export class MapLibreGLMap {
|
|||||||
geocoder: boolean,
|
geocoder: boolean,
|
||||||
geolocate: boolean
|
geolocate: boolean
|
||||||
) {
|
) {
|
||||||
maplibregl.setWorkerUrl(workerUrl);
|
|
||||||
this._maptilerKey = maptilerKey;
|
this._maptilerKey = maptilerKey;
|
||||||
this._styleManager = new StyleManager(this._mapStore, this._maptilerKey);
|
this._styleManager = new StyleManager(this._mapStore, this._maptilerKey);
|
||||||
const map = new maplibregl.Map({
|
const map = new maplibregl.Map({
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
import { i18n } from '$lib/i18n.svelte';
|
import { i18n } from '$lib/i18n.svelte';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import ButtonWithTooltip from '$lib/components/ButtonWithTooltip.svelte';
|
import ButtonWithTooltip from '$lib/components/ButtonWithTooltip.svelte';
|
||||||
import type { Map } from 'maplibre-gl';
|
|
||||||
|
|
||||||
const { streetViewSource } = settings;
|
const { streetViewSource } = settings;
|
||||||
|
|
||||||
@@ -21,7 +20,7 @@
|
|||||||
let container: HTMLElement;
|
let container: HTMLElement;
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
map.onLoad((map_: Map) => {
|
map.onLoad((map_: maplibregl.Map) => {
|
||||||
googleRedirect = new GoogleRedirect(map_);
|
googleRedirect = new GoogleRedirect(map_);
|
||||||
mapillaryLayer = new MapillaryLayer(
|
mapillaryLayer = new MapillaryLayer(
|
||||||
map_,
|
map_,
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
|
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
|
||||||
import type { Map, MapMouseEvent } from 'maplibre-gl';
|
|
||||||
|
|
||||||
export class GoogleRedirect {
|
export class GoogleRedirect {
|
||||||
map: Map;
|
map: maplibregl.Map;
|
||||||
enabled = false;
|
enabled = false;
|
||||||
|
|
||||||
constructor(map: Map) {
|
constructor(map: maplibregl.Map) {
|
||||||
this.map = map;
|
this.map = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,7 +24,7 @@ export class GoogleRedirect {
|
|||||||
this.map.off('click', this.openStreetView);
|
this.map.off('click', this.openStreetView);
|
||||||
}
|
}
|
||||||
|
|
||||||
openStreetView(e: MapMouseEvent) {
|
openStreetView(e: maplibregl.MapMouseEvent) {
|
||||||
window.open(
|
window.open(
|
||||||
`https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=${e.lngLat.lat},${e.lngLat.lng}`
|
`https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=${e.lngLat.lat},${e.lngLat.lng}`
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,10 +1,4 @@
|
|||||||
import {
|
import maplibregl, { type LayerSpecification, type VectorSourceSpecification } from 'maplibre-gl';
|
||||||
Map,
|
|
||||||
Marker,
|
|
||||||
type LayerSpecification,
|
|
||||||
type MapLayerMouseEvent,
|
|
||||||
type VectorSourceSpecification,
|
|
||||||
} from 'maplibre-gl';
|
|
||||||
import { Viewer, type ViewerBearingEvent } from 'mapillary-js/dist/mapillary.module';
|
import { Viewer, type ViewerBearingEvent } from 'mapillary-js/dist/mapillary.module';
|
||||||
import 'mapillary-js/dist/mapillary.css';
|
import 'mapillary-js/dist/mapillary.css';
|
||||||
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
|
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
|
||||||
@@ -49,9 +43,9 @@ const mapillaryImageLayer: LayerSpecification = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class MapillaryLayer {
|
export class MapillaryLayer {
|
||||||
map: Map;
|
map: maplibregl.Map;
|
||||||
layerEventManager: MapLayerEventManager;
|
layerEventManager: MapLayerEventManager;
|
||||||
marker: Marker;
|
marker: maplibregl.Marker;
|
||||||
viewer: Viewer;
|
viewer: Viewer;
|
||||||
|
|
||||||
active = false;
|
active = false;
|
||||||
@@ -62,7 +56,7 @@ export class MapillaryLayer {
|
|||||||
onMouseLeaveBinded = this.onMouseLeave.bind(this);
|
onMouseLeaveBinded = this.onMouseLeave.bind(this);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
map: Map,
|
map: maplibregl.Map,
|
||||||
layerEventManager: MapLayerEventManager,
|
layerEventManager: MapLayerEventManager,
|
||||||
container: HTMLElement,
|
container: HTMLElement,
|
||||||
popupOpen: { value: boolean }
|
popupOpen: { value: boolean }
|
||||||
@@ -81,7 +75,7 @@ export class MapillaryLayer {
|
|||||||
dot.className = 'maplibregl-user-location-dot';
|
dot.className = 'maplibregl-user-location-dot';
|
||||||
element.appendChild(dot);
|
element.appendChild(dot);
|
||||||
|
|
||||||
this.marker = new Marker({
|
this.marker = new maplibregl.Marker({
|
||||||
rotationAlignment: 'map',
|
rotationAlignment: 'map',
|
||||||
element,
|
element,
|
||||||
});
|
});
|
||||||
@@ -146,7 +140,7 @@ export class MapillaryLayer {
|
|||||||
this.popupOpen.value = false;
|
this.popupOpen.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseEnter(e: MapLayerMouseEvent) {
|
onMouseEnter(e: maplibregl.MapLayerMouseEvent) {
|
||||||
if (
|
if (
|
||||||
e.features &&
|
e.features &&
|
||||||
e.features.length > 0 &&
|
e.features.length > 0 &&
|
||||||
|
|||||||
@@ -9,17 +9,10 @@ import {
|
|||||||
} from '$lib/assets/layers';
|
} from '$lib/assets/layers';
|
||||||
import { getLayers } from '$lib/components/map/layer-control/utils';
|
import { getLayers } from '$lib/components/map/layer-control/utils';
|
||||||
import { i18n } from '$lib/i18n.svelte';
|
import { i18n } from '$lib/i18n.svelte';
|
||||||
import type {
|
|
||||||
Map,
|
|
||||||
GeoJSONSourceSpecification,
|
|
||||||
LayerSpecification,
|
|
||||||
StyleSpecification,
|
|
||||||
} from 'maplibre-gl';
|
|
||||||
|
|
||||||
const { currentBasemap, currentOverlays, customLayers, opacities, terrainSource, distanceUnits } =
|
const { currentBasemap, currentOverlays, customLayers, opacities, terrainSource } = settings;
|
||||||
settings;
|
|
||||||
|
|
||||||
const emptySource: GeoJSONSourceSpecification = {
|
const emptySource: maplibregl.GeoJSONSourceSpecification = {
|
||||||
type: 'geojson',
|
type: 'geojson',
|
||||||
data: {
|
data: {
|
||||||
type: 'FeatureCollection',
|
type: 'FeatureCollection',
|
||||||
@@ -38,18 +31,18 @@ export const ANCHOR_LAYER_KEY = {
|
|||||||
waypoints: 'waypoints-end',
|
waypoints: 'waypoints-end',
|
||||||
routingControls: 'routing-controls-end',
|
routingControls: 'routing-controls-end',
|
||||||
};
|
};
|
||||||
const anchorLayers: LayerSpecification[] = Object.values(ANCHOR_LAYER_KEY).map((id) => ({
|
const anchorLayers: maplibregl.LayerSpecification[] = Object.values(ANCHOR_LAYER_KEY).map((id) => ({
|
||||||
id: id,
|
id: id,
|
||||||
type: 'symbol',
|
type: 'symbol',
|
||||||
source: 'empty-source',
|
source: 'empty-source',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export class StyleManager {
|
export class StyleManager {
|
||||||
private _map: Writable<Map | null>;
|
private _map: Writable<maplibregl.Map | null>;
|
||||||
private _maptilerKey: string;
|
private _maptilerKey: string;
|
||||||
private _pastOverlays: Set<string> = new Set();
|
private _pastOverlays: Set<string> = new Set();
|
||||||
|
|
||||||
constructor(map: Writable<Map | null>, maptilerKey: string) {
|
constructor(map: Writable<maplibregl.Map | null>, maptilerKey: string) {
|
||||||
this._map = map;
|
this._map = map;
|
||||||
this._maptilerKey = maptilerKey;
|
this._maptilerKey = maptilerKey;
|
||||||
this._map.subscribe((map_) => {
|
this._map.subscribe((map_) => {
|
||||||
@@ -64,28 +57,18 @@ export class StyleManager {
|
|||||||
opacities.subscribe(() => this.updateOverlays());
|
opacities.subscribe(() => this.updateOverlays());
|
||||||
terrainSource.subscribe(() => this.updateTerrain());
|
terrainSource.subscribe(() => this.updateTerrain());
|
||||||
customLayers.subscribe(() => this.updateBasemap());
|
customLayers.subscribe(() => this.updateBasemap());
|
||||||
i18n.subscribe(() => this.updateBasemap());
|
|
||||||
distanceUnits.subscribe(() => {
|
|
||||||
const map = get(this._map);
|
|
||||||
if (map && (map.getLayer('contours_m') || map.getLayer('contours_ft'))) {
|
|
||||||
this.updateBasemap();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateBasemap() {
|
updateBasemap() {
|
||||||
const map_ = get(this._map);
|
const map_ = get(this._map);
|
||||||
if (!map_) return;
|
if (!map_) return;
|
||||||
let basemap = get(currentBasemap);
|
this.buildStyle().then((style) => map_.setStyle(style));
|
||||||
this.buildStyle(basemap).then((style) => {
|
|
||||||
if (get(currentBasemap) === basemap) map_.setStyle(style);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async buildStyle(basemap: string): Promise<StyleSpecification> {
|
async buildStyle(): Promise<maplibregl.StyleSpecification> {
|
||||||
const custom = get(customLayers);
|
const custom = get(customLayers);
|
||||||
|
|
||||||
const style: StyleSpecification = {
|
const style: maplibregl.StyleSpecification = {
|
||||||
version: 8,
|
version: 8,
|
||||||
projection: {
|
projection: {
|
||||||
type: 'globe',
|
type: 'globe',
|
||||||
@@ -96,31 +79,22 @@ export class StyleManager {
|
|||||||
layers: [],
|
layers: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let basemap = get(currentBasemap);
|
||||||
const basemapInfo = basemaps[basemap] ?? custom[basemap]?.value ?? basemaps[defaultBasemap];
|
const basemapInfo = basemaps[basemap] ?? custom[basemap]?.value ?? basemaps[defaultBasemap];
|
||||||
|
|
||||||
let basemapStyle = basemaps.openStreetMap as StyleSpecification;
|
let basemapStyle = basemaps.openStreetMap as maplibregl.StyleSpecification;
|
||||||
try {
|
try {
|
||||||
basemapStyle = await this.get(basemapInfo);
|
basemapStyle = await this.get(basemapInfo);
|
||||||
for (const source in basemapStyle.sources) {
|
|
||||||
const src = basemapStyle.sources[source];
|
|
||||||
if (
|
|
||||||
src &&
|
|
||||||
typeof src === 'object' &&
|
|
||||||
'url' in src &&
|
|
||||||
typeof src.url === 'string' &&
|
|
||||||
src.url.includes(maptilerKeyPlaceHolder)
|
|
||||||
) {
|
|
||||||
src.url = src.url.replace(maptilerKeyPlaceHolder, this._maptilerKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e.message);
|
console.error(e.message);
|
||||||
}
|
}
|
||||||
this.merge(style, basemapStyle);
|
this.merge(style, basemapStyle);
|
||||||
|
|
||||||
const terrain = this.getCurrentTerrain();
|
if (this._maptilerKey !== '') {
|
||||||
style.sources[terrain.source] = terrainSources[terrain.source];
|
const terrain = this.getCurrentTerrain();
|
||||||
style.terrain = terrain.exaggeration > 0 ? terrain : undefined;
|
style.sources[terrain.source] = terrainSources[terrain.source];
|
||||||
|
style.terrain = terrain.exaggeration > 0 ? terrain : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
style.layers.push(...anchorLayers);
|
style.layers.push(...anchorLayers);
|
||||||
|
|
||||||
@@ -192,6 +166,7 @@ export class StyleManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateTerrain() {
|
updateTerrain() {
|
||||||
|
if (this._maptilerKey === '') return;
|
||||||
const map_ = get(this._map);
|
const map_ = get(this._map);
|
||||||
if (!map_) return;
|
if (!map_) return;
|
||||||
|
|
||||||
@@ -209,9 +184,14 @@ export class StyleManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(styleInfo: StyleSpecification | string): Promise<StyleSpecification> {
|
async get(
|
||||||
|
styleInfo: maplibregl.StyleSpecification | string
|
||||||
|
): Promise<maplibregl.StyleSpecification> {
|
||||||
if (typeof styleInfo === 'string') {
|
if (typeof styleInfo === 'string') {
|
||||||
let styleUrl = styleInfo as string;
|
let styleUrl = styleInfo as string;
|
||||||
|
if (styleUrl.includes(maptilerKeyPlaceHolder)) {
|
||||||
|
styleUrl = styleUrl.replace(maptilerKeyPlaceHolder, this._maptilerKey);
|
||||||
|
}
|
||||||
const response = await fetch(styleUrl, { cache: 'force-cache' });
|
const response = await fetch(styleUrl, { cache: 'force-cache' });
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error fetching style "${styleInfo}": ${response.status}`);
|
throw new Error(`HTTP error fetching style "${styleInfo}": ${response.status}`);
|
||||||
@@ -223,48 +203,25 @@ export class StyleManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
merge(style: StyleSpecification, other: StyleSpecification) {
|
merge(style: maplibregl.StyleSpecification, other: maplibregl.StyleSpecification) {
|
||||||
style.sources = { ...style.sources, ...other.sources };
|
style.sources = { ...style.sources, ...other.sources };
|
||||||
const units = get(distanceUnits);
|
|
||||||
for (let layer of other.layers ?? []) {
|
for (let layer of other.layers ?? []) {
|
||||||
if ('source' in layer) {
|
|
||||||
if (layer.source == 'contours_m' && units === 'imperial') continue;
|
|
||||||
if (layer.source == 'contours_ft' && units !== 'imperial') continue;
|
|
||||||
}
|
|
||||||
if (layer.type === 'symbol' && layer.layout && layer.layout['text-field']) {
|
if (layer.type === 'symbol' && layer.layout && layer.layout['text-field']) {
|
||||||
const textField = layer.layout['text-field'];
|
const textField = layer.layout['text-field'];
|
||||||
if (Array.isArray(textField)) {
|
if (
|
||||||
if (
|
Array.isArray(textField) &&
|
||||||
textField.length == 4 &&
|
textField.length >= 2 &&
|
||||||
Array.isArray(textField[3]) &&
|
textField[0] === 'coalesce' &&
|
||||||
textField[3][0] === 'coalesce' &&
|
Array.isArray(textField[1]) &&
|
||||||
Array.isArray(textField[3][1]) &&
|
textField[1][0] === 'get' &&
|
||||||
textField[3][1][0] === 'get' &&
|
typeof textField[1][1] === 'string' &&
|
||||||
typeof textField[3][1][1] === 'string' &&
|
textField[1][1].startsWith('name')
|
||||||
textField[3][1][1].startsWith('name')
|
) {
|
||||||
) {
|
layer.layout['text-field'] = [
|
||||||
// OpenFreeMap styles
|
'coalesce',
|
||||||
layer.layout['text-field'] = [
|
['get', `name:${i18n.lang}`],
|
||||||
'coalesce',
|
['get', 'name'],
|
||||||
['get', `name:${i18n.lang}`],
|
];
|
||||||
['get', 'name'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
textField.length == 3 &&
|
|
||||||
textField[0] === 'coalesce' &&
|
|
||||||
Array.isArray(textField[1]) &&
|
|
||||||
textField[1][0] === 'get' &&
|
|
||||||
typeof textField[1][1] === 'string' &&
|
|
||||||
textField[1][1].startsWith('name')
|
|
||||||
) {
|
|
||||||
// OpenMapTiles styles
|
|
||||||
layer.layout['text-field'] = [
|
|
||||||
'coalesce',
|
|
||||||
['get', `name:${i18n.lang}`],
|
|
||||||
['get', 'name'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
style.layers.push(layer);
|
style.layers.push(layer);
|
||||||
@@ -279,6 +236,10 @@ export class StyleManager {
|
|||||||
|
|
||||||
getCurrentTerrain() {
|
getCurrentTerrain() {
|
||||||
const terrain = get(terrainSource);
|
const terrain = get(terrainSource);
|
||||||
|
const source = terrainSources[terrain];
|
||||||
|
if (source.url && source.url.includes(maptilerKeyPlaceHolder)) {
|
||||||
|
source.url = source.url.replace(maptilerKeyPlaceHolder, this._maptilerKey);
|
||||||
|
}
|
||||||
const map_ = get(this._map);
|
const map_ = get(this._map);
|
||||||
return {
|
return {
|
||||||
source: terrain,
|
source: terrain,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
import Clean from '$lib/components/toolbar/tools/Clean.svelte';
|
import Clean from '$lib/components/toolbar/tools/Clean.svelte';
|
||||||
import Reduce from '$lib/components/toolbar/tools/reduce/Reduce.svelte';
|
import Reduce from '$lib/components/toolbar/tools/reduce/Reduce.svelte';
|
||||||
import RoutingControlPopup from '$lib/components/toolbar/tools/routing/RoutingControlPopup.svelte';
|
import RoutingControlPopup from '$lib/components/toolbar/tools/routing/RoutingControlPopup.svelte';
|
||||||
import { Popup } from 'maplibre-gl';
|
import maplibregl from 'maplibre-gl';
|
||||||
import { settings } from '$lib/logic/settings';
|
import { settings } from '$lib/logic/settings';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
@@ -23,11 +23,11 @@
|
|||||||
const { minimizeRoutingMenu } = settings;
|
const { minimizeRoutingMenu } = settings;
|
||||||
|
|
||||||
let popupElement: HTMLDivElement | undefined = $state(undefined);
|
let popupElement: HTMLDivElement | undefined = $state(undefined);
|
||||||
let popup: Popup | undefined = $derived.by(() => {
|
let popup: maplibregl.Popup | undefined = $derived.by(() => {
|
||||||
if (!popupElement) {
|
if (!popupElement) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
let popup = new Popup({
|
let popup = new maplibregl.Popup({
|
||||||
closeButton: false,
|
closeButton: false,
|
||||||
maxWidth: undefined,
|
maxWidth: undefined,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
import { getURLForLanguage } from '$lib/utils';
|
import { getURLForLanguage } from '$lib/utils';
|
||||||
import { Trash2 } from '@lucide/svelte';
|
import { Trash2 } from '@lucide/svelte';
|
||||||
import { map } from '$lib/components/map/map';
|
import { map } from '$lib/components/map/map';
|
||||||
import type { GeoJSONSource, LngLat } from 'maplibre-gl';
|
import type { GeoJSONSource } from 'maplibre-gl';
|
||||||
import { selection } from '$lib/logic/selection';
|
import { selection } from '$lib/logic/selection';
|
||||||
import { fileActions } from '$lib/logic/file-actions';
|
import { fileActions } from '$lib/logic/file-actions';
|
||||||
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
|
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
let cleanType = $state(CleanType.INSIDE);
|
let cleanType = $state(CleanType.INSIDE);
|
||||||
let deleteTrackpoints = $state(true);
|
let deleteTrackpoints = $state(true);
|
||||||
let deleteWaypoints = $state(true);
|
let deleteWaypoints = $state(true);
|
||||||
let rectangleCoordinates: LngLat[] = $state([]);
|
let rectangleCoordinates: maplibregl.LngLat[] = $state([]);
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if ($map) {
|
if ($map) {
|
||||||
|
|||||||
@@ -163,9 +163,6 @@ export class ReducedGPXLayerCollection {
|
|||||||
reduce() {
|
reduce() {
|
||||||
let itemsAndPoints = new Map<ListItem, TrackPoint[]>();
|
let itemsAndPoints = new Map<ListItem, TrackPoint[]>();
|
||||||
this._simplified.forEach(([item, maxPts, points], itemFullId) => {
|
this._simplified.forEach(([item, maxPts, points], itemFullId) => {
|
||||||
if (!get(selection).hasAnyParent(item)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
itemsAndPoints.set(
|
itemsAndPoints.set(
|
||||||
item,
|
item,
|
||||||
points
|
points
|
||||||
|
|||||||
@@ -41,7 +41,6 @@
|
|||||||
import { fileActions, getFileIds, newGPXFile } from '$lib/logic/file-actions';
|
import { fileActions, getFileIds, newGPXFile } from '$lib/logic/file-actions';
|
||||||
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
|
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
|
||||||
import { RoutingControls, routingControls } from './routing-controls';
|
import { RoutingControls, routingControls } from './routing-controls';
|
||||||
import type { Popup } from 'maplibre-gl';
|
|
||||||
|
|
||||||
let {
|
let {
|
||||||
minimized = $bindable(false),
|
minimized = $bindable(false),
|
||||||
@@ -52,7 +51,7 @@
|
|||||||
}: {
|
}: {
|
||||||
minimized?: boolean;
|
minimized?: boolean;
|
||||||
minimizable?: boolean;
|
minimizable?: boolean;
|
||||||
popup?: Popup;
|
popup?: maplibregl.Popup;
|
||||||
popupElement?: HTMLDivElement;
|
popupElement?: HTMLDivElement;
|
||||||
class?: string;
|
class?: string;
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
import { distance, type Coordinates, TrackPoint, TrackSegment, Track, projectedPoint } from 'gpx';
|
import { distance, type Coordinates, TrackPoint, TrackSegment, Track, projectedPoint } from 'gpx';
|
||||||
import { get, writable, type Readable } from 'svelte/store';
|
import { get, writable, type Readable } from 'svelte/store';
|
||||||
import {
|
import maplibregl, {
|
||||||
type MapMouseEvent,
|
type MapMouseEvent,
|
||||||
type GeoJSONSource,
|
type GeoJSONSource,
|
||||||
type MapLayerMouseEvent,
|
type MapLayerMouseEvent,
|
||||||
type MapLayerTouchEvent,
|
type MapLayerTouchEvent,
|
||||||
Popup,
|
|
||||||
Point,
|
|
||||||
} from 'maplibre-gl';
|
} from 'maplibre-gl';
|
||||||
import { route } from './routing';
|
import { route } from './routing';
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
@@ -52,7 +50,7 @@ export class RoutingControls {
|
|||||||
}
|
}
|
||||||
> = new Map();
|
> = new Map();
|
||||||
anchors: GeoJSON.Feature<GeoJSON.Point, AnchorProperties>[] = [];
|
anchors: GeoJSON.Feature<GeoJSON.Point, AnchorProperties>[] = [];
|
||||||
popup: Popup;
|
popup: maplibregl.Popup;
|
||||||
popupElement: HTMLElement;
|
popupElement: HTMLElement;
|
||||||
fileUnsubscribe: () => void = () => {};
|
fileUnsubscribe: () => void = () => {};
|
||||||
unsubscribes: Function[] = [];
|
unsubscribes: Function[] = [];
|
||||||
@@ -63,7 +61,7 @@ export class RoutingControls {
|
|||||||
|
|
||||||
draggedAnchorIndex: number | null = null;
|
draggedAnchorIndex: number | null = null;
|
||||||
lastDraggedAnchorEventTime: number = 0;
|
lastDraggedAnchorEventTime: number = 0;
|
||||||
draggingStartingPosition: Point = new Point(0, 0);
|
draggingStartingPosition: maplibregl.Point = new maplibregl.Point(0, 0);
|
||||||
onMouseEnterBinded: () => void = this.onMouseEnter.bind(this);
|
onMouseEnterBinded: () => void = this.onMouseEnter.bind(this);
|
||||||
onMouseLeaveBinded: () => void = this.onMouseLeave.bind(this);
|
onMouseLeaveBinded: () => void = this.onMouseLeave.bind(this);
|
||||||
onClickBinded: (e: MapLayerMouseEvent) => void = this.onClick.bind(this);
|
onClickBinded: (e: MapLayerMouseEvent) => void = this.onClick.bind(this);
|
||||||
@@ -82,7 +80,7 @@ export class RoutingControls {
|
|||||||
constructor(
|
constructor(
|
||||||
fileId: string,
|
fileId: string,
|
||||||
file: Readable<GPXFileWithStatistics | undefined>,
|
file: Readable<GPXFileWithStatistics | undefined>,
|
||||||
popup: Popup,
|
popup: maplibregl.Popup,
|
||||||
popupElement: HTMLElement
|
popupElement: HTMLElement
|
||||||
) {
|
) {
|
||||||
this.fileId = fileId;
|
this.fileId = fileId;
|
||||||
@@ -185,7 +183,7 @@ export class RoutingControls {
|
|||||||
|
|
||||||
this.layers.forEach((layer, zoom) => {
|
this.layers.forEach((layer, zoom) => {
|
||||||
try {
|
try {
|
||||||
let source = map_.getSource(layer.id) as GeoJSONSource | undefined;
|
let source = map_.getSource(layer.id) as maplibregl.GeoJSONSource | undefined;
|
||||||
if (source) {
|
if (source) {
|
||||||
source.setData({
|
source.setData({
|
||||||
type: 'FeatureCollection',
|
type: 'FeatureCollection',
|
||||||
@@ -522,7 +520,7 @@ export class RoutingControls {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async appendAnchor(e: MapMouseEvent) {
|
async appendAnchor(e: maplibregl.MapMouseEvent) {
|
||||||
// Add a new anchor to the end of the last segment
|
// Add a new anchor to the end of the last segment
|
||||||
if (get(streetViewEnabled) && get(streetViewSource) === 'google') {
|
if (get(streetViewEnabled) && get(streetViewSource) === 'google') {
|
||||||
return;
|
return;
|
||||||
@@ -611,7 +609,7 @@ export class RoutingControls {
|
|||||||
await this.routeBetweenAnchors([lastAnchor, newAnchor], [lastAnchorPoint, newAnchorPoint]);
|
await this.routeBetweenAnchors([lastAnchor, newAnchor], [lastAnchorPoint, newAnchorPoint]);
|
||||||
}
|
}
|
||||||
|
|
||||||
addIntermediateAnchor(e: MapMouseEvent) {
|
addIntermediateAnchor(e: maplibregl.MapMouseEvent) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if (this.temporaryAnchor !== null) {
|
if (this.temporaryAnchor !== null) {
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ import { get } from 'svelte/store';
|
|||||||
import { fileStateCollection } from '$lib/logic/file-state';
|
import { fileStateCollection } from '$lib/logic/file-state';
|
||||||
import { fileActions } from '$lib/logic/file-actions';
|
import { fileActions } from '$lib/logic/file-actions';
|
||||||
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
|
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
|
||||||
import type { Map, GeoJSONSource, MapLayerMouseEvent } from 'maplibre-gl';
|
import type { GeoJSONSource } from 'maplibre-gl';
|
||||||
import { ANCHOR_LAYER_KEY } from '$lib/components/map/style';
|
import { ANCHOR_LAYER_KEY } from '$lib/components/map/style';
|
||||||
import type { MapLayerEventManager } from '$lib/components/map/map-layer-event-manager';
|
import type { MapLayerEventManager } from '$lib/components/map/map-layer-event-manager';
|
||||||
import { loadSVGIcon } from '$lib/utils';
|
import { loadSVGIcon } from '$lib/utils';
|
||||||
|
|
||||||
export class SplitControls {
|
export class SplitControls {
|
||||||
map: Map;
|
map: maplibregl.Map;
|
||||||
layerEventManager: MapLayerEventManager;
|
layerEventManager: MapLayerEventManager;
|
||||||
unsubscribes: Function[] = [];
|
unsubscribes: Function[] = [];
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ export class SplitControls {
|
|||||||
layerOnMouseLeaveBinded: () => void = this.layerOnMouseLeave.bind(this);
|
layerOnMouseLeaveBinded: () => void = this.layerOnMouseLeave.bind(this);
|
||||||
layerOnClickBinded: (e: any) => void = this.layerOnClick.bind(this);
|
layerOnClickBinded: (e: any) => void = this.layerOnClick.bind(this);
|
||||||
|
|
||||||
constructor(map: Map, layerEventManager: MapLayerEventManager) {
|
constructor(map: maplibregl.Map, layerEventManager: MapLayerEventManager) {
|
||||||
this.map = map;
|
this.map = map;
|
||||||
this.layerEventManager = layerEventManager;
|
this.layerEventManager = layerEventManager;
|
||||||
loadSVGIcon(
|
loadSVGIcon(
|
||||||
@@ -160,7 +160,7 @@ export class SplitControls {
|
|||||||
mapCursor.notify(MapCursorState.SPLIT_CONTROL, false);
|
mapCursor.notify(MapCursorState.SPLIT_CONTROL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
layerOnClick(e: MapLayerMouseEvent) {
|
layerOnClick(e: maplibregl.MapLayerMouseEvent) {
|
||||||
let coordinates = (e.features![0].geometry as GeoJSON.Point).coordinates;
|
let coordinates = (e.features![0].geometry as GeoJSON.Point).coordinates;
|
||||||
fileActions.split(
|
fileActions.split(
|
||||||
get(splitAs),
|
get(splitAs),
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
import { fileActions } from '$lib/logic/file-actions';
|
import { fileActions } from '$lib/logic/file-actions';
|
||||||
import { map } from '$lib/components/map/map';
|
import { map } from '$lib/components/map/map';
|
||||||
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
|
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
|
||||||
import { Marker } from 'maplibre-gl';
|
import maplibregl from 'maplibre-gl';
|
||||||
import { getSvgForSymbol } from '$lib/components/map/gpx-layer/gpx-layer';
|
import { getSvgForSymbol } from '$lib/components/map/gpx-layer/gpx-layer';
|
||||||
|
|
||||||
let props: {
|
let props: {
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
let marker: Marker | null = null;
|
let marker: maplibregl.Marker | null = null;
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
if ($selectedWaypoint) {
|
if ($selectedWaypoint) {
|
||||||
@@ -125,7 +125,7 @@
|
|||||||
let element = document.createElement('div');
|
let element = document.createElement('div');
|
||||||
element.classList.add('w-8', 'h-8');
|
element.classList.add('w-8', 'h-8');
|
||||||
element.innerHTML = getSvgForSymbol(symbolKey);
|
element.innerHTML = getSvgForSymbol(symbolKey);
|
||||||
marker = new Marker({
|
marker = new maplibregl.Marker({
|
||||||
element,
|
element,
|
||||||
anchor: 'bottom',
|
anchor: 'bottom',
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ These controls allow you to navigate the map, zoom in and out, and switch betwee
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ This tool allows you to add elevation data to traces and [points of interest](..
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ El botó de capa de mapa permet canviar entre diferents mapes base i alternar ca
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Aquesta eina permet afegir dades d'elevació a traces i [punts d'interès](../gp
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ Tlačítko mapové vrstvy umožňuje přepínat mezi různými podkladovými map
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Tento nástroj umožňuje přidat údaje o nadmořské výšce ke stopám a [bod
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ The map layers button allows you to switch between different basemaps, and toggl
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ This tool allows you to add elevation data to traces and [points of interest](..
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ Mit der Schaltfläche Karten-Ebenen können Sie zwischen verschiedenen Basemaps
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Fahre mit der Maus über die Karte, um die <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails-Wanderkarte</a> über der <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a>-Basiskarte anzuzeigen.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -50,5 +50,5 @@ Um die Ausrichtung und Neigung der Karte zu steuern, können Sie die Karte auch
|
|||||||
|
|
||||||
### <Maximize2 size="16" class="inline-block" style="margin-bottom: 2px" /> Full screen
|
### <Maximize2 size="16" class="inline-block" style="margin-bottom: 2px" /> Full screen
|
||||||
|
|
||||||
Vollbildmodus ein- oder ausschalten.
|
Enter or exit full screen mode.
|
||||||
Du kannst auch <kbd>F11</kbd> drücken, um zu wechseln, oder <kbd>Escape</kbd> zum Beenden.
|
You can also press <kbd>F11</kbd> to toggle, or <kbd>Escape</kbd> to exit.
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Mit diesem Tool kannst du Höhendaten zu Routen und [Points of Interest] (../gpx
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Die Höhendaten werden von <a href="https://maptiler.com" target="_blank">MapTiler</a> bereitgestellt.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
Mehr über die Herkunft und Genauigkeit erfährst du in der <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">Dokumentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ The map layers button allows you to switch between different basemaps, and toggl
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ This tool allows you to add elevation data to traces and [points of interest](..
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ Only one basemap can be displayed at a time.
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ This tool allows you to add elevation data to traces and [points of interest](..
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
@@ -59,7 +59,7 @@ El botón de capas de mapa le permite cambiar entre diferentes mapas bases y alt
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Pasa el ratón sobre el mapa para que la capa de <a href="https://hiking.waymarkedtrails.org" target="_blank">Caminatas por Sendas Marcadas</a> aparezca superpuesta al mapa base topográfico.
|
Pasa el ratón sobre el mapa para que la capa de <a href="https://hiking.waymarkedtrails.org" target="_blank">Caminatas por Sendas Marcadas</a> aparezca superpuesta al mapa base <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler</a>.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Esta herramienta permite añadir datos de elevación a los rastros y [puntos de
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Los datos de elevación son proporcionados por <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Los datos de notificación son proporcionados por <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
Puede aprender más sobre su origen y precisión en la <a href="https://mapterhorn.com/attribution/" target="_blank">documentación</a>.
|
Puedes aprender más sobre su origen y precisión en la <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentación</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ Maparen geruzen botoiak mapa-oinarri desberdinen artean aldatzeko aukera ematen
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Tresna honen bidez elebazio datuak gehitzen ahal dira ibilbidetan eta [interesgu
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ The map layers button allows you to switch between different basemaps, and toggl
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ This tool allows you to add elevation data to traces and [points of interest](..
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ Le bouton des couches de la carte vous permet de basculer entre différents fond
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Survolez la carte pour afficher la superposition des chemins de randonnée <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails</a> au fond de carte topographique.
|
Survolez la carte pour afficher la superposition des chemins de randonnée <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails</a> au fond de carte <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a>.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Cet outil vous permet d'ajouter des données d'altitude aux traces et aux [point
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Les données d'altitude sont fournies par <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Les données d'altitude sont fournies par <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
Vous pouvez en apprendre plus sur leur origine et précision dans la <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
Vous pouvez en apprendre plus sur leur origine et précision dans la <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ The map layers button allows you to switch between different basemaps, and toggl
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ This tool allows you to add elevation data to traces and [points of interest](..
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ The map layers button allows you to switch between different basemaps, and toggl
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Ez az eszköz lehetővé teszi magassági adatok hozzáadását a nyomvonalakhoz
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ The map layers button allows you to switch between different basemaps, and toggl
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ This tool allows you to add elevation data to traces and [points of interest](..
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ Il pulsante dei livelli di mappa consente di passare da una basemap all'altra, e
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Questo strumento ti permette di aggiungere dati di altimetria a tracce e [punti
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ The map layers button allows you to switch between different basemaps, and toggl
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ This tool allows you to add elevation data to traces and [points of interest](..
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ The map layers button allows you to switch between different basemaps, and toggl
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ This tool allows you to add elevation data to traces and [points of interest](..
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ The map layers button allows you to switch between different basemaps, and toggl
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ This tool allows you to add elevation data to traces and [points of interest](..
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ Met de kaartlagen knop kun je wisselen tussen verschillende basiskaarten, en kaa
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Beweeg over de kaart om de <a href="https://hiking.waymarkedtrails.org" target="_blank">Gemarkeerde sporen wandelen</a> overlay te tonen bovenop de topografische basiskaart.
|
Beweeg over de kaart om de <a href="https://hiking.waymarkedtrails.org" target="_blank">Gemarkeerde sporen wandelen</a> overlay te tonen bovenop de <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ title: Instellingen
|
|||||||
|
|
||||||
Wijzig de eenheden die worden gebruikt om afstanden in de interface weer te geven.
|
Wijzig de eenheden die worden gebruikt om afstanden in de interface weer te geven.
|
||||||
|
|
||||||
### <Zap size="16" class="inline-block" style="margin-bottom: 2px" /> Snelheidseenheden
|
### <Zap size="16" class="inline-block" style="margin-bottom: 2px" /> Snelheids eenheden
|
||||||
|
|
||||||
Verander de eenheden die worden gebruikt om snelheden in de interface weer te geven.
|
Verander de eenheden die worden gebruikt om velocities in de interface weer te geven.
|
||||||
Je kunt kiezen tussen afstand per uur of minuten per afstand, wat geschikter kan zijn voor het uitvoeren van activiteiten.
|
Je kunt kiezen tussen afstand per uur of minuten per afstand, wat geschikter kan zijn voor het uitvoeren van activiteiten.
|
||||||
|
|
||||||
### <Thermometer size="16" class="inline-block" style="margin-bottom: 2px" /> Temperatuureenheden
|
### <Thermometer size="16" class="inline-block" style="margin-bottom: 2px" /> Temperatuureenheden
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Met dit gereedschap kun je hoogtegegevens toevoegen aan sporen en [interessante
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Hoogtegegevens worden verstrekt door <a href="https://maptiler.com" target="_blank">Mapterhorn</a>.
|
Hoogtegegevens worden verstrekt door <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
Je kunt meer leren over de oorsprong en nauwkeurigheid in de <a href="https://mapterhorn.com/attribution/" target="_blank">documentatie</a>.
|
Je kunt meer leren over de oorsprong en nauwkeurigheid in de <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentatie</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ The map layers button allows you to switch between different basemaps, and toggl
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ This tool allows you to add elevation data to traces and [points of interest](..
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ The map layers button allows you to switch between different basemaps, and toggl
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ To narzędzie pozwala dodawać dane dotyczące wysokości do tras i [punktów za
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ O botão de camadas de mapa permite que você alterne entre diferentes mapas e a
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Esta ferramenta permite que você adicione dados de elevação a rastros e [pont
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ The map layers button allows you to switch between different basemaps, and toggl
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ This tool allows you to add elevation data to traces and [points of interest](..
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ The map layers button allows you to switch between different basemaps, and toggl
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ This tool allows you to add elevation data to traces and [points of interest](..
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ The map controls are located on the right side of the interface.
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ title: Высота
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ Dugme za slojeve mape vam omogućava da prelazite između različitih osnovnih
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Postavite pokazivač miša iznad mape da biste prikazali preklapanje <a href="https://hiking.waymarkedtrails.org" target="_blank">Planinarske staze sa obeleženim putevima</a> preko osnovne mape <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a>.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Ovaj alat vam omogućava da dodate podatke o nadmorskoj visini trasama i [tačk
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Podatke o nadmorskoj visini obezbeđuje <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
Više o njegovom poreklu i tačnosti možete saznati u <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">dokumentaciji</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ The map layers button allows you to switch between different basemaps, and toggl
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Detta verktyg låter dig lägga till höjddata till spår och [intressanta plats
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ The map layers button allows you to switch between different basemaps, and toggl
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ This tool allows you to add elevation data to traces and [points of interest](..
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ Harita katmanları düğmesi, farklı temel haritalar arasında geçiş yapmanı
|
|||||||
<DocsLayers />
|
<DocsLayers />
|
||||||
<span class="text-sm text-center mt-2">
|
<span class="text-sm text-center mt-2">
|
||||||
|
|
||||||
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the topographic basemap.
|
Hover over the map to show the <a href="https://hiking.waymarkedtrails.org" target="_blank">Waymarked Trails hiking</a> overlay on top of the <a href="https://www.maptiler.com/maps/outdoor-topo/" target="_blank">MapTiler Topo</a> basemap.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Bu araç izlere ve [ilgi noktalarına](../gpx) yükseklik verisi eklemenizi veya
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Elevation data is provided by <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
Elevation data is provided by <a href="https://maptiler.com" target="_blank">MapTiler</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
You can learn more about its origin and accuracy in the <a href="https://docs.maptiler.com/guides/map-tiling-hosting/data-hosting/rgb-terrain-by-maptiler/" target="_blank">documentation</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Часті питання
|
title: FAQ
|
||||||
---
|
---
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -8,28 +8,28 @@ title: Часті питання
|
|||||||
|
|
||||||
# { title }
|
# { title }
|
||||||
|
|
||||||
### Чи потрібно робити пожертву, щоб користуватися сайтом?
|
### Do I need to donate to use the website?
|
||||||
|
|
||||||
Ні.
|
No.
|
||||||
Сайтом можна користуватися безкоштовно, і так буде завжди (доки це фінансово можливо).
|
The website is free to use and always will be (as long as it is financially sustainable).
|
||||||
Проте ми вдячні за пожертви, вони допомагають підтримувати роботу сайту.
|
However, donations are appreciated and help keep the website running.
|
||||||
|
|
||||||
### Чому вибрано саме цей маршрут, а не інший? **Або** як додати щось на карту?
|
### Why is this route chosen over that one? _Or_ how can I add something to the map?
|
||||||
|
|
||||||
**gpx.studio** використовує дані <a href="https://www.openstreetmap.org/" target="_blank">OpenStreetMap</a>, який є відкритими картами світу, що створюється спільнотою.
|
**gpx.studio** uses data from <a href="https://www.openstreetmap.org/" target="_blank">OpenStreetMap</a>, which is an open and collaborative world map.
|
||||||
Тобто ви можете покращувати карту, додаючи або редагуючи дані в OpenStreetMap.
|
This means you can contribute to the map by adding or editing data on OpenStreetMap.
|
||||||
|
|
||||||
Якщо ви ще ніколи не долучалися до OpenStreetMap, ось як можна запропонувати зміни:
|
If you have never contributed to OpenStreetMap before, here is how you can suggest changes:
|
||||||
|
|
||||||
1. Перейдіть до місця на <a href="https://www.openstreetmap.org/" target="_blank">карті</a>, де хочете додати або відредагувати дані.
|
1. Go to the location where you want to add or edit data on the <a href="https://www.openstreetmap.org/" target="_blank">map</a>.
|
||||||
2. Скористайтеся інструментом <button>Запитати об’єкти</button> праворуч, щоб переглянути наявні дані.
|
2. Use the <button>Query features</button> tool on the right to inspect the existing data.
|
||||||
3. Клацніть правою кнопкою миші в потрібному місці та виберіть <button>Додати примітку тут</button>.
|
3. Right-click on the location and select <button>Add a note here</button>.
|
||||||
4. У примітці вкажіть, що потрібно виправити або додати, і натисніть <button>Додати примітку</button>, щоб надіслати її.
|
4. Explain what is incorrect or missing in the note and click <button>Add note</button> to submit it.
|
||||||
|
|
||||||
Потім досвідченіший учасник OpenStreetMap перегляне вашу примітку й внесе потрібні зміни.
|
Someone more experienced with OpenStreetMap will then review your note and make the necessary changes.
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Докладніше про те, як долучитися до OpenStreetMap, можна дізнатися <a href="https://wiki.openstreetmap.org/wiki/How_to_contribute" target="_blank">тут</a>.
|
More information on how to contribute to OpenStreetMap can be found <a href="https://wiki.openstreetmap.org/wiki/How_to_contribute" target="_blank">here</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -54,32 +54,32 @@ title: Файли та статистика
|
|||||||
Крім того, у дереві файлів можна переглядати [треки, сегменти та цікаві місця](./gpx), що містяться у файлах, за допомогою розгортальних розділів.
|
Крім того, у дереві файлів можна переглядати [треки, сегменти та цікаві місця](./gpx), що містяться у файлах, за допомогою розгортальних розділів.
|
||||||
|
|
||||||
Ви також можете застосовувати [дії редагування](./menu/edit) та [інструменти](./toolbar) до елементів внутрішніх файлів.
|
Ви також можете застосовувати [дії редагування](./menu/edit) та [інструменти](./toolbar) до елементів внутрішніх файлів.
|
||||||
Крім того, внутрішні елементи можна перетягувати, щоб змінювати їхній порядок, переміщувати в ієрархії або навіть переносити до іншого файлу.
|
Furthermore, you can drag and drop the inner items to reorder them, or move them in the hierarchy or even to another file.
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Розмір списку файлів можна налаштувати, перетягнувши розділювач між картою та списком файлів.
|
The size of the file list can be adjusted by dragging the separator between the map and the file list.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|
||||||
## Профіль висоти та статистика
|
## Elevation profile and statistics
|
||||||
|
|
||||||
У нижній частині інтерфейсу можна знайти профіль висоти та статистику для поточного виділення.
|
At the bottom of the interface, you can find the elevation profile and statistics for the current selection.
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Розмір профілю висоти можна змінити, перетягнувши розділювач між картою та профілем висоти.
|
The size of the elevation profile can be adjusted by dragging the separator between the map and the elevation profile.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|
||||||
### Інтерактивна статистика
|
### Interactive statistics
|
||||||
|
|
||||||
Під час наведення на профіль висоти підказка показує статистику в позиції курсора.
|
When hovering over the elevation profile, a tooltip will show statistics at the cursor position.
|
||||||
|
|
||||||
Щоб отримати статистику для певної ділянки профілю висоти, можна створити прямокутне виділення на профілі.
|
To get the statistics for a specific section of the elevation profile, you can drag a selection rectangle on the profile.
|
||||||
Клацніть на профілі, щоб скинути виділення.
|
Click on the profile to reset the selection.
|
||||||
|
|
||||||
Також можна використовувати колесо миші, щоб наближати й віддаляти профіль висоти, а також переміщатися ліворуч і праворуч, перетягуючи профіль із затиснутою клавішею <kbd>Shift</kbd>.
|
You can also use the mouse wheel to zoom in and out on the elevation profile, and move left and right by dragging the profile while holding the <kbd>Shift</kbd> key.
|
||||||
|
|
||||||
<div class="h-48 w-full">
|
<div class="h-48 w-full">
|
||||||
<ElevationProfile
|
<ElevationProfile
|
||||||
@@ -98,12 +98,12 @@ title: Файли та статистика
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
### Додаткові дані
|
### Additional data
|
||||||
|
|
||||||
За допомогою кнопки <kbd><ChartNoAxesColumn size="16" class="inline-block" style="margin-bottom: 2px"/></kbd> у правому нижньому куті профілю висоти можна за бажанням розфарбувати профіль висоти за:
|
Using the <kbd><ChartNoAxesColumn size="16" class="inline-block" style="margin-bottom: 2px"/></kbd> button at the bottom-right of the elevation profile, you can optionally color the elevation profile by:
|
||||||
|
|
||||||
- даними про **ухил**, обчисленими з даних висоти; або
|
- **slope** information computed from the elevation data, or
|
||||||
- даними про **покриття** чи **категорію дороги** з тегів <a href="https://www.openstreetmap.org/" target="_blank">OpenStreetMap</a> <a href="https://wiki.openstreetmap.org/wiki/Key:surface" target="_blank">surface</a> і <a href="https://wiki.openstreetmap.org/wiki/Key:highway" target="_blank">highway</a>.
|
- **surface** or **category** data coming from <a href="https://www.openstreetmap.org/" target="_blank">OpenStreetMap</a>'s <a href="https://wiki.openstreetmap.org/wiki/Key:surface" target="_blank">surface</a> and <a href="https://wiki.openstreetmap.org/wiki/Key:highway" target="_blank">highway</a> tags.
|
||||||
Це доступно лише для файлів, створених у **gpx.studio**.
|
This is only available for files created with **gpx.studio**.
|
||||||
|
|
||||||
Якщо вибраний трек містить відповідні дані, на профілі висоти також можна відобразити **швидкість**, **пульс**, **каденс**, **температуру** та **потужність**.
|
If your selection includes it, you can also visualize: **speed**, **heart rate**, **cadence**, **temperature** and **power** data on the elevation profile.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Перші кроки
|
title: Getting started
|
||||||
---
|
---
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -8,30 +8,30 @@ title: Перші кроки
|
|||||||
|
|
||||||
# { title }
|
# { title }
|
||||||
|
|
||||||
Ласкаво просимо до офіційного посібника **gpx.studio**!
|
Welcome to the official guide for **gpx.studio**!
|
||||||
Цей посібник проведе вас через усі компоненти й інструменти інтерфейсу та допоможе впевнено користуватися застосунком.
|
This guide will walk you through all the components and tools of the interface, helping you become a proficient user of the application.
|
||||||
|
|
||||||
<DocsImage src="getting-started/interface" alt="Інтерфейс gpx.studio." />
|
<DocsImage src="getting-started/interface" alt="The gpx.studio interface." />
|
||||||
|
|
||||||
Як показано на знімку екрана вище, інтерфейс поділено на чотири основні розділи, розташовані навколо карти.
|
As shown in the screenshot above, the interface is divided into four main sections organized around the map.
|
||||||
Перед тим, як перейти до деталей кожного розділу, коротко оглянемо інтерфейс.
|
Before we dive into the details of each section, let's have a quick overview of the interface.
|
||||||
|
|
||||||
## Меню
|
## Menu
|
||||||
|
|
||||||
У верхній частині інтерфейсу розташоване [головне меню](./menu).
|
At the top of the interface, you will find the [main menu](./menu).
|
||||||
Тут можна виконувати типові дії: відкривати, закривати й експортувати файли, скасовувати та повторювати дії, а також змінювати налаштування застосунку.
|
This is where you can access common actions such as opening, closing, and exporting files, undoing and redoing actions, and adjusting the application settings.
|
||||||
|
|
||||||
## Файли та статистика
|
## Файли та статистика
|
||||||
|
|
||||||
У нижній частині інтерфейсу розташований список файлів, відкритих у застосунку.
|
At the bottom of the interface, you will find the list of files currently open in the application.
|
||||||
Клацніть на файл, щоб вибрати його й показати статистику під списком.
|
You can click on a file to select it and display its statistics below the list.
|
||||||
В [окремому розділі](./files-and-stats) ми пояснимо, як вибирати кілька файлів і перемикатися на деревоподібне відображення для розширеного керування файлами.
|
In the [dedicated section](./files-and-stats), we will explain how to select multiple files and switch to a tree layout for advanced file management.
|
||||||
|
|
||||||
## Панель інструментів
|
## Toolbar
|
||||||
|
|
||||||
У лівій частині інтерфейсу розташована [панель інструментів](./toolbar) з усіма інструментами для редагування файлів.
|
On the left side of the interface, you will find the [toolbar](./toolbar), which contains all the tools you can use to edit your files.
|
||||||
|
|
||||||
## Керування картою
|
## Map controls
|
||||||
|
|
||||||
Нарешті, у правій частині інтерфейсу розташовані елементи [керування картою](./map-controls).
|
Finally, on the right side of the interface, you will find the [map controls](./map-controls).
|
||||||
Вони дають змогу переміщатися картою, наближати й віддаляти її, а також перемикатися між різними стилями карти.
|
These controls allow you to navigate the map, zoom in and out, and switch between different map styles.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Формат GPX-файлу
|
title: GPX file format
|
||||||
---
|
---
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -8,27 +8,27 @@ title: Формат GPX-файлу
|
|||||||
|
|
||||||
# { title }
|
# { title }
|
||||||
|
|
||||||
<a href="https://www.topografix.com/gpx.asp" target="_blank">Формат GPX-файлу</a> це відкритий стандарт для обміну GPS-даними між застосунками та GPS-пристроями.
|
The <a href="https://www.topografix.com/gpx.asp" target="_blank">GPX file format</a> is an open standard for exchanging GPS data between applications and GPS devices.
|
||||||
По суті, він складається з набору GPS-точок, які описують один або кілька GPS-треків, а також, за бажанням, точки інтересу.
|
It essentially consists of a series of GPS points encoding one or multiple GPS traces, and, optionally, some points of interest.
|
||||||
|
|
||||||
GPX-файли також можуть містити метадані, серед яких для користувачів найкорисніші поля **назва** та **опис**.
|
GPX files may also contain metadata, of which the **name** and **description** fields are the most useful for users.
|
||||||
|
|
||||||
### <Waypoints size="16" class="inline-block" style="margin-bottom: 2px" /> Треки, сегменти та GPS-точки
|
### <Waypoints size="16" class="inline-block" style="margin-bottom: 2px" /> Tracks, segments, and GPS points
|
||||||
|
|
||||||
Як згадано вище, GPX-файл може містити кілька GPS-треків.
|
As mentioned above, a GPX file can contain multiple GPS traces.
|
||||||
Вони організовані в ієрархічну структуру, де треки розташовані на верхньому рівні.
|
These are organized in a hierarchical structure, with tracks at the top level.
|
||||||
|
|
||||||
- **Трек** складається з послідовності окремих сегментів.
|
- A **track** is made of a sequence of disconnected segments.
|
||||||
Крім того, він може містити метадані, такі як **назва**, **опис** і **властивості вигляду**.
|
Furthermore, it can contain metadata such as a **name**, a **description**, and **appearance properties**.
|
||||||
- **Сегмент** — це послідовність GPS-точок, які утворюють безперервний шлях.
|
- A **segment** is a sequence of GPS points that form a continuous path.
|
||||||
- **GPS-точка** — це місце з широтою, довготою, також додатково часовою міткою й висотою.
|
- A **GPS point** is a location with a latitude, a longitude, and optionally a timestamp and an altitude.
|
||||||
Деякі пристрої також зберігають додаткову інформацію, такі як пульс, каденс, температуру та потужність.
|
Some devices also store additional information such as heart rate, cadence, temperature, and power.
|
||||||
|
|
||||||
У більшості випадків GPX-файли містять один трек з одним сегментом.
|
In most cases, GPX files contain a single track with a single segment.
|
||||||
Однак описана вище ієрархія дає змогу використовувати складніші сценарії, наприклад планувати багатоденні подорожі з кількома варіантами маршруту на кожен день.
|
However, the hierarchy described above allows for more advanced use cases, such as planning multi-day trips with several variants for each day.
|
||||||
|
|
||||||
### <MapPin size="16" class="inline-block" style="margin-bottom: 2px" /> Точки інтересу
|
### <MapPin size="16" class="inline-block" style="margin-bottom: 2px" /> Points of interest
|
||||||
|
|
||||||
**Точки інтересу** (технічно вони називаються **waypoints**) позначають цікаві місця, які можна показувати на GPS-пристрої або цифровій карті.
|
**Points of interest** (technically called _waypoints_) represent locations of interest to show either on a GPS device or on a digital map.
|
||||||
|
|
||||||
Окрім координат, точка інтересу може мати **назву** та **опис**.
|
In addition to its coordinates, a point of interest can have a **name** and a **description**.
|
||||||
|
|||||||