mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2026-07-28 14:18:39 +00:00
Compare commits
38 Commits
e21c4bf46e
..
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| 6a0d434371 | |||
| b319440a57 | |||
| b0d78b5f3c | |||
| 2e8b2d6f30 | |||
| 5259d007c9 | |||
| cb36725a46 | |||
| deef1bab47 | |||
| 108880f8cd | |||
| 37a659831b | |||
| fde6bafc10 | |||
| 86f4fc3394 | |||
| 565589fc94 | |||
| 4ef92e5abd | |||
| 4537ea4730 | |||
| 7f8751fa38 | |||
| 1954bbd764 | |||
| befcba00b4 | |||
| 9d2da80893 | |||
| 043d368c74 | |||
| bb11d3375b | |||
| bfe5961e27 | |||
| 17559913fd | |||
| 55590d68a6 | |||
| 8e9f16c460 | |||
| c60b64f24f | |||
| fdb6fe4e52 | |||
| 0bf168e67e | |||
| d762a45eb9 | |||
| 548ab9a459 | |||
| 315c1f6a61 | |||
| 98257bee12 | |||
| 5561b7d9fe | |||
| 320887206c | |||
| 04a1bf6a55 | |||
| 0989371874 | |||
| 3dcd6e52d3 | |||
| 0f06d0d461 | |||
| db33310a10 |
@@ -70,8 +70,9 @@ 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) — routing engine
|
- [GraphHopper](https://github.com/graphhopper/graphhopper) — powerful routing engine
|
||||||
- [OpenStreetMap](https://www.openstreetmap.org) — map data used by most of the map layers, and by the routing engine
|
- [OpenStreetMap](https://www.openstreetmap.org) — open 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
|
||||||
|
|
||||||
|
|||||||
Generated
+70
-67
@@ -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": "^5.21.1",
|
"maplibre-gl": "^6.0.0",
|
||||||
"sanitize-html": "^2.17.0",
|
"sanitize-html": "^2.17.0",
|
||||||
"sortablejs": "^1.15.6"
|
"sortablejs": "^1.15.6"
|
||||||
},
|
},
|
||||||
@@ -3236,13 +3236,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mapbox/jsonlint-lines-primitives": {
|
"node_modules/@mapbox/jsonlint-lines-primitives": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.3",
|
||||||
|
"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": ">= 0.6"
|
"node": ">= 22"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"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": {
|
||||||
@@ -3253,24 +3258,32 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@mapbox/tiny-sdf": {
|
"node_modules/@mapbox/tiny-sdf": {
|
||||||
"version": "2.0.7",
|
"version": "2.2.0",
|
||||||
|
"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": "0.0.1",
|
"version": "1.0.0",
|
||||||
|
"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": "2.0.4",
|
"version": "3.0.0",
|
||||||
|
"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": "^4.0.1"
|
"pbf": "^5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mapbox/vector-tile/node_modules/pbf": {
|
"node_modules/@mapbox/vector-tile/node_modules/pbf": {
|
||||||
"version": "4.0.1",
|
"version": "5.1.2",
|
||||||
|
"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"
|
||||||
@@ -3279,18 +3292,13 @@
|
|||||||
"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.0.4",
|
"version": "6.1.1",
|
||||||
|
"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.0.2"
|
"kdbush": "^4.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@maplibre/maplibre-gl-geocoder": {
|
"node_modules/@maplibre/maplibre-gl-geocoder": {
|
||||||
@@ -3311,15 +3319,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@maplibre/maplibre-gl-style-spec": {
|
"node_modules/@maplibre/maplibre-gl-style-spec": {
|
||||||
"version": "24.8.1",
|
"version": "26.2.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.2",
|
"@mapbox/jsonlint-lines-primitives": "^2.0.3",
|
||||||
"@mapbox/unitbezier": "^0.0.1",
|
"@mapbox/unitbezier": "^1.0.0",
|
||||||
"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": {
|
||||||
@@ -3329,31 +3338,29 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@maplibre/mlt": {
|
"node_modules/@maplibre/mlt": {
|
||||||
"version": "1.1.8",
|
"version": "1.1.12",
|
||||||
|
"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.0",
|
"version": "4.3.2",
|
||||||
|
"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",
|
||||||
"@types/supercluster": "^7.1.3",
|
"pbf": "^5.1.0"
|
||||||
"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": "4.0.1",
|
"version": "5.1.2",
|
||||||
|
"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"
|
||||||
@@ -4289,13 +4296,6 @@
|
|||||||
"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,6 +5720,8 @@
|
|||||||
},
|
},
|
||||||
"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": {
|
||||||
@@ -5733,7 +5735,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/kdbush": {
|
"node_modules/kdbush": {
|
||||||
"version": "4.0.2",
|
"version": "4.1.0",
|
||||||
|
"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": {
|
||||||
@@ -6154,25 +6158,25 @@
|
|||||||
"license": "(MIT AND Zlib)"
|
"license": "(MIT AND Zlib)"
|
||||||
},
|
},
|
||||||
"node_modules/maplibre-gl": {
|
"node_modules/maplibre-gl": {
|
||||||
"version": "5.22.0",
|
"version": "6.0.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.0.7",
|
"@mapbox/tiny-sdf": "^2.2.0",
|
||||||
"@mapbox/unitbezier": "^0.0.1",
|
"@mapbox/unitbezier": "^1.0.0",
|
||||||
"@mapbox/vector-tile": "^2.0.4",
|
"@mapbox/vector-tile": "^3.0.0",
|
||||||
"@mapbox/whoots-js": "^3.1.0",
|
"@maplibre/geojson-vt": "^6.1.1",
|
||||||
"@maplibre/geojson-vt": "^6.0.4",
|
"@maplibre/maplibre-gl-style-spec": "^26.1.0",
|
||||||
"@maplibre/maplibre-gl-style-spec": "^24.8.1",
|
"@maplibre/mlt": "^1.1.12",
|
||||||
"@maplibre/mlt": "^1.1.8",
|
"@maplibre/vt-pbf": "^4.3.2",
|
||||||
"@maplibre/vt-pbf": "^4.3.0",
|
|
||||||
"@types/geojson": "^7946.0.16",
|
"@types/geojson": "^7946.0.16",
|
||||||
"earcut": "^3.0.2",
|
"earcut": "^3.2.3",
|
||||||
"gl-matrix": "^3.4.4",
|
"gl-matrix": "^3.4.4",
|
||||||
"kdbush": "^4.0.2",
|
"kdbush": "^4.1.0",
|
||||||
"murmurhash-js": "^1.0.0",
|
"murmurhash-js": "^1.0.0",
|
||||||
"pbf": "^4.0.1",
|
"pbf": "^5.1.2",
|
||||||
"potpack": "^2.1.0",
|
"potpack": "^2.1.0",
|
||||||
"quickselect": "^3.0.0",
|
"quickselect": "^3.0.0",
|
||||||
"tinyqueue": "^3.0.0"
|
"tinyqueue": "^3.0.0"
|
||||||
@@ -6186,11 +6190,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/maplibre-gl/node_modules/earcut": {
|
"node_modules/maplibre-gl/node_modules/earcut": {
|
||||||
"version": "3.0.2",
|
"version": "3.2.3",
|
||||||
|
"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": "4.0.1",
|
"version": "5.1.2",
|
||||||
|
"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"
|
||||||
@@ -6251,6 +6259,8 @@
|
|||||||
},
|
},
|
||||||
"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"
|
||||||
@@ -6785,6 +6795,8 @@
|
|||||||
},
|
},
|
||||||
"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": {
|
||||||
@@ -6920,10 +6932,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"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",
|
||||||
@@ -7157,13 +7165,6 @@
|
|||||||
"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",
|
||||||
@@ -7405,6 +7406,8 @@
|
|||||||
},
|
},
|
||||||
"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": "^5.21.1",
|
"maplibre-gl": "^6.0.0",
|
||||||
"sanitize-html": "^2.17.0",
|
"sanitize-html": "^2.17.0",
|
||||||
"sortablejs": "^1.15.6"
|
"sortablejs": "^1.15.6"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 | maplibregl.StyleSpecification;
|
value: string | StyleSpecification;
|
||||||
};
|
};
|
||||||
|
|
||||||
type OverpassQueryData = {
|
type OverpassQueryData = {
|
||||||
@@ -1449,7 +1449,7 @@ export const overpassQueryData: Record<string, OverpassQueryData> = {
|
|||||||
color: 'DarkBlue',
|
color: 'DarkBlue',
|
||||||
},
|
},
|
||||||
tags: {
|
tags: {
|
||||||
railway: 'station',
|
railway: ['station', 'halt'],
|
||||||
},
|
},
|
||||||
symbol: 'Ground Transportation',
|
symbol: 'Ground Transportation',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
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,
|
||||||
@@ -45,26 +46,6 @@
|
|||||||
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;
|
||||||
}
|
}
|
||||||
@@ -90,6 +71,28 @@
|
|||||||
].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(() => {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
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',
|
||||||
@@ -17,7 +18,7 @@
|
|||||||
let control: CustomControl | null = null;
|
let control: CustomControl | null = null;
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
map.onLoad((map: maplibregl.Map) => {
|
map.onLoad((map: 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');
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
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: maplibregl.Map) {
|
export function createPopups(map: Map) {
|
||||||
removePopups();
|
removePopups();
|
||||||
waypointPopup = new MapPopup(map, {
|
waypointPopup = new MapPopup(map, {
|
||||||
closeButton: false,
|
closeButton: false,
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { get, type Readable } from 'svelte/store';
|
import { get, type Readable } from 'svelte/store';
|
||||||
import maplibregl, {
|
import {
|
||||||
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';
|
||||||
@@ -120,7 +121,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: maplibregl.Point = new maplibregl.Point(0, 0);
|
draggingStartingPosition: Point = new Point(0, 0);
|
||||||
unsubscribe: Function[] = [];
|
unsubscribe: Function[] = [];
|
||||||
|
|
||||||
updateBinded: () => void = this.update.bind(this);
|
updateBinded: () => void = this.update.bind(this);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
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;
|
||||||
@@ -21,7 +22,7 @@
|
|||||||
selectedOverpassTree,
|
selectedOverpassTree,
|
||||||
} = settings;
|
} = settings;
|
||||||
|
|
||||||
map.onLoad((_map: maplibregl.Map) => {
|
map.onLoad((_map: Map) => {
|
||||||
if (overpassLayer) {
|
if (overpassLayer) {
|
||||||
overpassLayer.remove();
|
overpassLayer.remove();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,9 @@
|
|||||||
poi: PopupItem<any>;
|
poi: PopupItem<any>;
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
let tags: Record<string, string> = $derived(poi ? JSON.parse(poi.item.tags) : {});
|
let tags: Record<string, string> = $derived(
|
||||||
|
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 !== '') {
|
||||||
@@ -88,6 +90,14 @@
|
|||||||
<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 { GeoJSONSource } from 'maplibre-gl';
|
import type { Map as MapLibreMap, 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';
|
||||||
@@ -28,7 +28,7 @@ export class OverpassLayer {
|
|||||||
minZoom = 12;
|
minZoom = 12;
|
||||||
queryZoom = 12;
|
queryZoom = 12;
|
||||||
expirationTime = 7 * 24 * 3600 * 1000;
|
expirationTime = 7 * 24 * 3600 * 1000;
|
||||||
map: maplibregl.Map;
|
map: MapLibreMap;
|
||||||
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: maplibregl.Map, layerEventManager: MapLayerEventManager) {
|
constructor(map: MapLibreMap, 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,10 +1,19 @@
|
|||||||
import { fileStateCollection } from '$lib/logic/file-state';
|
import { fileStateCollection } from '$lib/logic/file-state';
|
||||||
import maplibregl from 'maplibre-gl';
|
import {
|
||||||
|
LngLatBounds,
|
||||||
|
MapMouseEvent,
|
||||||
|
MapTouchEvent,
|
||||||
|
Point,
|
||||||
|
type Map,
|
||||||
|
type MapGeoJSONFeature,
|
||||||
|
type MapLayerMouseEvent,
|
||||||
|
type MapLayerTouchEvent,
|
||||||
|
} from 'maplibre-gl';
|
||||||
|
|
||||||
type MapLayerMouseEventListener = (e: maplibregl.MapLayerMouseEvent) => void;
|
type MapLayerMouseEventListener = (e: MapLayerMouseEvent) => void;
|
||||||
type MapLayerTouchEventListener = (e: maplibregl.MapLayerTouchEvent) => void;
|
type MapLayerTouchEventListener = (e: MapLayerTouchEvent) => void;
|
||||||
type MapLayerListener = {
|
type MapLayerListener = {
|
||||||
features: maplibregl.MapGeoJSONFeature[];
|
features: MapGeoJSONFeature[];
|
||||||
mousemoves: MapLayerMouseEventListener[];
|
mousemoves: MapLayerMouseEventListener[];
|
||||||
mouseenters: MapLayerMouseEventListener[];
|
mouseenters: MapLayerMouseEventListener[];
|
||||||
mouseleaves: MapLayerMouseEventListener[];
|
mouseleaves: MapLayerMouseEventListener[];
|
||||||
@@ -15,10 +24,10 @@ type MapLayerListener = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class MapLayerEventManager {
|
export class MapLayerEventManager {
|
||||||
private _map: maplibregl.Map;
|
private _map: Map;
|
||||||
private _listeners: Record<string, MapLayerListener> = {};
|
private _listeners: Record<string, MapLayerListener> = {};
|
||||||
|
|
||||||
constructor(map: maplibregl.Map) {
|
constructor(map: 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'));
|
||||||
@@ -141,7 +150,7 @@ export class MapLayerEventManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleMouseMove(e: maplibregl.MapMouseEvent) {
|
private _handleMouseMove(e: 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) => {
|
||||||
@@ -150,29 +159,20 @@ 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 maplibregl.MapMouseEvent(
|
const event = new MapMouseEvent('mouseenter', e.target, e.originalEvent, {
|
||||||
'mouseenter',
|
features: featuresByLayer[layerId]!,
|
||||||
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 maplibregl.MapMouseEvent(
|
const event = new MapMouseEvent('mouseleave', e.target, e.originalEvent);
|
||||||
'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 maplibregl.MapMouseEvent('mousemove', e.target, e.originalEvent, {
|
const event = new 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,49 +181,39 @@ export class MapLayerEventManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleMouseClick(type: string, e: maplibregl.MapMouseEvent) {
|
private _handleMouseClick(type: string, e: 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 maplibregl.MapMouseEvent('click', e.target, e.originalEvent, {
|
const event = new 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 maplibregl.MapMouseEvent(
|
const event = new MapMouseEvent('contextmenu', e.target, e.originalEvent, {
|
||||||
'contextmenu',
|
features: features,
|
||||||
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 maplibregl.MapMouseEvent(
|
const event = new MapMouseEvent('mousedown', e.target, e.originalEvent, {
|
||||||
'mousedown',
|
features: features,
|
||||||
e.target,
|
});
|
||||||
e.originalEvent,
|
|
||||||
{
|
|
||||||
features: features,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
listener.mousedowns.forEach((l) => l(event));
|
listener.mousedowns.forEach((l) => l(event));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleTouchStart(e: maplibregl.MapTouchEvent) {
|
private _handleTouchStart(e: 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: maplibregl.MapLayerTouchEvent = new maplibregl.MapTouchEvent(
|
const event: MapLayerTouchEvent = new MapTouchEvent(
|
||||||
'touchstart',
|
'touchstart',
|
||||||
e.target,
|
e.target,
|
||||||
e.originalEvent
|
e.originalEvent
|
||||||
@@ -234,18 +224,15 @@ export class MapLayerEventManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getBounds(point: maplibregl.Point) {
|
private _getBounds(point: Point) {
|
||||||
const delta = 30;
|
const delta = 30;
|
||||||
return new maplibregl.LngLatBounds(
|
return new 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(
|
private _filterLayersIntersectingBounds(layerIds: string[], bounds: LngLatBounds): string[] {
|
||||||
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', '');
|
||||||
@@ -261,7 +248,7 @@ export class MapLayerEventManager {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getRenderedFeaturesByLayer(e: maplibregl.MapMouseEvent | maplibregl.MapTouchEvent) {
|
private _getRenderedFeaturesByLayer(e: MapMouseEvent | 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)
|
||||||
@@ -270,7 +257,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, maplibregl.MapGeoJSONFeature[]> = {};
|
const featuresByLayer: Record<string, 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 maplibregl from 'maplibre-gl';
|
import { LngLat, Map, MapMouseEvent, Popup, type PopupOptions } 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: maplibregl.Map;
|
map: Map;
|
||||||
popup: maplibregl.Popup;
|
popup: 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: maplibregl.Map, options?: maplibregl.PopupOptions) {
|
constructor(map: Map, options?: PopupOptions) {
|
||||||
this.map = map;
|
this.map = map;
|
||||||
this.popup = new maplibregl.Popup(options);
|
this.popup = new 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: maplibregl.MapMouseEvent) {
|
maybeHide(e: 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 maplibregl.LngLat(0, 0);
|
return new 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 maplibregl.LngLat(item.item.lon, item.item.lat);
|
: new LngLat(item.item.lon, item.item.lat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import maplibregl from 'maplibre-gl';
|
import * as 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';
|
||||||
@@ -39,6 +40,7 @@ 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,6 +9,7 @@
|
|||||||
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;
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@
|
|||||||
let container: HTMLElement;
|
let container: HTMLElement;
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
map.onLoad((map_: maplibregl.Map) => {
|
map.onLoad((map_: Map) => {
|
||||||
googleRedirect = new GoogleRedirect(map_);
|
googleRedirect = new GoogleRedirect(map_);
|
||||||
mapillaryLayer = new MapillaryLayer(
|
mapillaryLayer = new MapillaryLayer(
|
||||||
map_,
|
map_,
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
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: maplibregl.Map;
|
map: Map;
|
||||||
enabled = false;
|
enabled = false;
|
||||||
|
|
||||||
constructor(map: maplibregl.Map) {
|
constructor(map: Map) {
|
||||||
this.map = map;
|
this.map = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,7 +25,7 @@ export class GoogleRedirect {
|
|||||||
this.map.off('click', this.openStreetView);
|
this.map.off('click', this.openStreetView);
|
||||||
}
|
}
|
||||||
|
|
||||||
openStreetView(e: maplibregl.MapMouseEvent) {
|
openStreetView(e: 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,4 +1,10 @@
|
|||||||
import maplibregl, { type LayerSpecification, type VectorSourceSpecification } from 'maplibre-gl';
|
import {
|
||||||
|
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';
|
||||||
@@ -43,9 +49,9 @@ const mapillaryImageLayer: LayerSpecification = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class MapillaryLayer {
|
export class MapillaryLayer {
|
||||||
map: maplibregl.Map;
|
map: Map;
|
||||||
layerEventManager: MapLayerEventManager;
|
layerEventManager: MapLayerEventManager;
|
||||||
marker: maplibregl.Marker;
|
marker: Marker;
|
||||||
viewer: Viewer;
|
viewer: Viewer;
|
||||||
|
|
||||||
active = false;
|
active = false;
|
||||||
@@ -56,7 +62,7 @@ export class MapillaryLayer {
|
|||||||
onMouseLeaveBinded = this.onMouseLeave.bind(this);
|
onMouseLeaveBinded = this.onMouseLeave.bind(this);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
map: maplibregl.Map,
|
map: Map,
|
||||||
layerEventManager: MapLayerEventManager,
|
layerEventManager: MapLayerEventManager,
|
||||||
container: HTMLElement,
|
container: HTMLElement,
|
||||||
popupOpen: { value: boolean }
|
popupOpen: { value: boolean }
|
||||||
@@ -75,7 +81,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 maplibregl.Marker({
|
this.marker = new Marker({
|
||||||
rotationAlignment: 'map',
|
rotationAlignment: 'map',
|
||||||
element,
|
element,
|
||||||
});
|
});
|
||||||
@@ -140,7 +146,7 @@ export class MapillaryLayer {
|
|||||||
this.popupOpen.value = false;
|
this.popupOpen.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseEnter(e: maplibregl.MapLayerMouseEvent) {
|
onMouseEnter(e: MapLayerMouseEvent) {
|
||||||
if (
|
if (
|
||||||
e.features &&
|
e.features &&
|
||||||
e.features.length > 0 &&
|
e.features.length > 0 &&
|
||||||
|
|||||||
@@ -9,11 +9,17 @@ 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, distanceUnits } =
|
||||||
settings;
|
settings;
|
||||||
|
|
||||||
const emptySource: maplibregl.GeoJSONSourceSpecification = {
|
const emptySource: GeoJSONSourceSpecification = {
|
||||||
type: 'geojson',
|
type: 'geojson',
|
||||||
data: {
|
data: {
|
||||||
type: 'FeatureCollection',
|
type: 'FeatureCollection',
|
||||||
@@ -32,18 +38,18 @@ export const ANCHOR_LAYER_KEY = {
|
|||||||
waypoints: 'waypoints-end',
|
waypoints: 'waypoints-end',
|
||||||
routingControls: 'routing-controls-end',
|
routingControls: 'routing-controls-end',
|
||||||
};
|
};
|
||||||
const anchorLayers: maplibregl.LayerSpecification[] = Object.values(ANCHOR_LAYER_KEY).map((id) => ({
|
const anchorLayers: 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<maplibregl.Map | null>;
|
private _map: Writable<Map | null>;
|
||||||
private _maptilerKey: string;
|
private _maptilerKey: string;
|
||||||
private _pastOverlays: Set<string> = new Set();
|
private _pastOverlays: Set<string> = new Set();
|
||||||
|
|
||||||
constructor(map: Writable<maplibregl.Map | null>, maptilerKey: string) {
|
constructor(map: Writable<Map | null>, maptilerKey: string) {
|
||||||
this._map = map;
|
this._map = map;
|
||||||
this._maptilerKey = maptilerKey;
|
this._maptilerKey = maptilerKey;
|
||||||
this._map.subscribe((map_) => {
|
this._map.subscribe((map_) => {
|
||||||
@@ -58,6 +64,7 @@ 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(() => {
|
distanceUnits.subscribe(() => {
|
||||||
const map = get(this._map);
|
const map = get(this._map);
|
||||||
if (map && (map.getLayer('contours_m') || map.getLayer('contours_ft'))) {
|
if (map && (map.getLayer('contours_m') || map.getLayer('contours_ft'))) {
|
||||||
@@ -75,10 +82,10 @@ export class StyleManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async buildStyle(basemap: string): Promise<maplibregl.StyleSpecification> {
|
async buildStyle(basemap: string): Promise<StyleSpecification> {
|
||||||
const custom = get(customLayers);
|
const custom = get(customLayers);
|
||||||
|
|
||||||
const style: maplibregl.StyleSpecification = {
|
const style: StyleSpecification = {
|
||||||
version: 8,
|
version: 8,
|
||||||
projection: {
|
projection: {
|
||||||
type: 'globe',
|
type: 'globe',
|
||||||
@@ -91,7 +98,7 @@ export class StyleManager {
|
|||||||
|
|
||||||
const basemapInfo = basemaps[basemap] ?? custom[basemap]?.value ?? basemaps[defaultBasemap];
|
const basemapInfo = basemaps[basemap] ?? custom[basemap]?.value ?? basemaps[defaultBasemap];
|
||||||
|
|
||||||
let basemapStyle = basemaps.openStreetMap as maplibregl.StyleSpecification;
|
let basemapStyle = basemaps.openStreetMap as StyleSpecification;
|
||||||
try {
|
try {
|
||||||
basemapStyle = await this.get(basemapInfo);
|
basemapStyle = await this.get(basemapInfo);
|
||||||
for (const source in basemapStyle.sources) {
|
for (const source in basemapStyle.sources) {
|
||||||
@@ -202,9 +209,7 @@ export class StyleManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(
|
async get(styleInfo: StyleSpecification | string): Promise<StyleSpecification> {
|
||||||
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;
|
||||||
const response = await fetch(styleUrl, { cache: 'force-cache' });
|
const response = await fetch(styleUrl, { cache: 'force-cache' });
|
||||||
@@ -218,7 +223,7 @@ export class StyleManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
merge(style: maplibregl.StyleSpecification, other: maplibregl.StyleSpecification) {
|
merge(style: StyleSpecification, other: StyleSpecification) {
|
||||||
style.sources = { ...style.sources, ...other.sources };
|
style.sources = { ...style.sources, ...other.sources };
|
||||||
const units = get(distanceUnits);
|
const units = get(distanceUnits);
|
||||||
for (let layer of other.layers ?? []) {
|
for (let layer of other.layers ?? []) {
|
||||||
|
|||||||
@@ -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 maplibregl from 'maplibre-gl';
|
import { Popup } 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: maplibregl.Popup | undefined = $derived.by(() => {
|
let popup: Popup | undefined = $derived.by(() => {
|
||||||
if (!popupElement) {
|
if (!popupElement) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
let popup = new maplibregl.Popup({
|
let popup = new 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 } from 'maplibre-gl';
|
import type { GeoJSONSource, LngLat } 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: maplibregl.LngLat[] = $state([]);
|
let rectangleCoordinates: LngLat[] = $state([]);
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if ($map) {
|
if ($map) {
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
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),
|
||||||
@@ -51,7 +52,7 @@
|
|||||||
}: {
|
}: {
|
||||||
minimized?: boolean;
|
minimized?: boolean;
|
||||||
minimizable?: boolean;
|
minimizable?: boolean;
|
||||||
popup?: maplibregl.Popup;
|
popup?: Popup;
|
||||||
popupElement?: HTMLDivElement;
|
popupElement?: HTMLDivElement;
|
||||||
class?: string;
|
class?: string;
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
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 maplibregl, {
|
import {
|
||||||
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';
|
||||||
@@ -50,7 +52,7 @@ export class RoutingControls {
|
|||||||
}
|
}
|
||||||
> = new Map();
|
> = new Map();
|
||||||
anchors: GeoJSON.Feature<GeoJSON.Point, AnchorProperties>[] = [];
|
anchors: GeoJSON.Feature<GeoJSON.Point, AnchorProperties>[] = [];
|
||||||
popup: maplibregl.Popup;
|
popup: Popup;
|
||||||
popupElement: HTMLElement;
|
popupElement: HTMLElement;
|
||||||
fileUnsubscribe: () => void = () => {};
|
fileUnsubscribe: () => void = () => {};
|
||||||
unsubscribes: Function[] = [];
|
unsubscribes: Function[] = [];
|
||||||
@@ -61,7 +63,7 @@ export class RoutingControls {
|
|||||||
|
|
||||||
draggedAnchorIndex: number | null = null;
|
draggedAnchorIndex: number | null = null;
|
||||||
lastDraggedAnchorEventTime: number = 0;
|
lastDraggedAnchorEventTime: number = 0;
|
||||||
draggingStartingPosition: maplibregl.Point = new maplibregl.Point(0, 0);
|
draggingStartingPosition: Point = new 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);
|
||||||
@@ -80,7 +82,7 @@ export class RoutingControls {
|
|||||||
constructor(
|
constructor(
|
||||||
fileId: string,
|
fileId: string,
|
||||||
file: Readable<GPXFileWithStatistics | undefined>,
|
file: Readable<GPXFileWithStatistics | undefined>,
|
||||||
popup: maplibregl.Popup,
|
popup: Popup,
|
||||||
popupElement: HTMLElement
|
popupElement: HTMLElement
|
||||||
) {
|
) {
|
||||||
this.fileId = fileId;
|
this.fileId = fileId;
|
||||||
@@ -183,7 +185,7 @@ export class RoutingControls {
|
|||||||
|
|
||||||
this.layers.forEach((layer, zoom) => {
|
this.layers.forEach((layer, zoom) => {
|
||||||
try {
|
try {
|
||||||
let source = map_.getSource(layer.id) as maplibregl.GeoJSONSource | undefined;
|
let source = map_.getSource(layer.id) as GeoJSONSource | undefined;
|
||||||
if (source) {
|
if (source) {
|
||||||
source.setData({
|
source.setData({
|
||||||
type: 'FeatureCollection',
|
type: 'FeatureCollection',
|
||||||
@@ -520,7 +522,7 @@ export class RoutingControls {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async appendAnchor(e: maplibregl.MapMouseEvent) {
|
async appendAnchor(e: 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;
|
||||||
@@ -609,7 +611,7 @@ export class RoutingControls {
|
|||||||
await this.routeBetweenAnchors([lastAnchor, newAnchor], [lastAnchorPoint, newAnchorPoint]);
|
await this.routeBetweenAnchors([lastAnchor, newAnchor], [lastAnchorPoint, newAnchorPoint]);
|
||||||
}
|
}
|
||||||
|
|
||||||
addIntermediateAnchor(e: maplibregl.MapMouseEvent) {
|
addIntermediateAnchor(e: 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 { GeoJSONSource } from 'maplibre-gl';
|
import type { Map, GeoJSONSource, MapLayerMouseEvent } 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: maplibregl.Map;
|
map: 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: maplibregl.Map, layerEventManager: MapLayerEventManager) {
|
constructor(map: 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: maplibregl.MapLayerMouseEvent) {
|
layerOnClick(e: 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 maplibregl from 'maplibre-gl';
|
import { Marker } 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: maplibregl.Marker | null = null;
|
let marker: 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 maplibregl.Marker({
|
marker = new Marker({
|
||||||
element,
|
element,
|
||||||
anchor: 'bottom',
|
anchor: 'bottom',
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
Enter or exit full screen mode.
|
Vollbildmodus ein- oder ausschalten.
|
||||||
You can also press <kbd>F11</kbd> to toggle, or <kbd>Escape</kbd> to exit.
|
Du kannst auch <kbd>F11</kbd> drücken, um zu wechseln, oder <kbd>Escape</kbd> zum Beenden.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: FAQ
|
title: Часті питання
|
||||||
---
|
---
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -8,28 +8,28 @@ title: FAQ
|
|||||||
|
|
||||||
# { 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** uses data from <a href="https://www.openstreetmap.org/" target="_blank">OpenStreetMap</a>, which is an open and collaborative world map.
|
**gpx.studio** використовує дані <a href="https://www.openstreetmap.org/" target="_blank">OpenStreetMap</a>, який є відкритими картами світу, що створюється спільнотою.
|
||||||
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:
|
Якщо ви ще ніколи не долучалися до OpenStreetMap, ось як можна запропонувати зміни:
|
||||||
|
|
||||||
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>.
|
1. Перейдіть до місця на <a href="https://www.openstreetmap.org/" target="_blank">карті</a>, де хочете додати або відредагувати дані.
|
||||||
2. Use the <button>Query features</button> tool on the right to inspect the existing data.
|
2. Скористайтеся інструментом <button>Запитати об’єкти</button> праворуч, щоб переглянути наявні дані.
|
||||||
3. Right-click on the location and select <button>Add a note here</button>.
|
3. Клацніть правою кнопкою миші в потрібному місці та виберіть <button>Додати примітку тут</button>.
|
||||||
4. Explain what is incorrect or missing in the note and click <button>Add note</button> to submit it.
|
4. У примітці вкажіть, що потрібно виправити або додати, і натисніть <button>Додати примітку</button>, щоб надіслати її.
|
||||||
|
|
||||||
Someone more experienced with OpenStreetMap will then review your note and make the necessary changes.
|
Потім досвідченіший учасник OpenStreetMap перегляне вашу примітку й внесе потрібні зміни.
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
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>.
|
Докладніше про те, як долучитися до OpenStreetMap, можна дізнатися <a href="https://wiki.openstreetmap.org/wiki/How_to_contribute" target="_blank">тут</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.
|
Клацніть на профілі, щоб скинути виділення.
|
||||||
|
|
||||||
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.
|
Також можна використовувати колесо миші, щоб наближати й віддаляти профіль висоти, а також переміщатися ліворуч і праворуч, перетягуючи профіль із затиснутою клавішею <kbd>Shift</kbd>.
|
||||||
|
|
||||||
<div class="h-48 w-full">
|
<div class="h-48 w-full">
|
||||||
<ElevationProfile
|
<ElevationProfile
|
||||||
@@ -98,12 +98,12 @@ You can also use the mouse wheel to zoom in and out on the elevation profile, an
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
### Additional data
|
### Додаткові дані
|
||||||
|
|
||||||
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:
|
За допомогою кнопки <kbd><ChartNoAxesColumn size="16" class="inline-block" style="margin-bottom: 2px"/></kbd> у правому нижньому куті профілю висоти можна за бажанням розфарбувати профіль висоти за:
|
||||||
|
|
||||||
- **slope** information computed from the elevation data, or
|
- даними про **ухил**, обчисленими з даних висоти; або
|
||||||
- **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.
|
- даними про **покриття** чи **категорію дороги** з тегів <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>.
|
||||||
This is only available for files created with **gpx.studio**.
|
Це доступно лише для файлів, створених у **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: Getting started
|
title: Перші кроки
|
||||||
---
|
---
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -8,30 +8,30 @@ title: Getting started
|
|||||||
|
|
||||||
# { title }
|
# { title }
|
||||||
|
|
||||||
Welcome to the official guide for **gpx.studio**!
|
Ласкаво просимо до офіційного посібника **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="The gpx.studio interface." />
|
<DocsImage src="getting-started/interface" alt="Інтерфейс gpx.studio." />
|
||||||
|
|
||||||
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
|
## Меню
|
||||||
|
|
||||||
At the top of the interface, you will find the [main menu](./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.
|
Клацніть на файл, щоб вибрати його й показати статистику під списком.
|
||||||
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.
|
В [окремому розділі](./files-and-stats) ми пояснимо, як вибирати кілька файлів і перемикатися на деревоподібне відображення для розширеного керування файлами.
|
||||||
|
|
||||||
## 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.
|
У лівій частині інтерфейсу розташована [панель інструментів](./toolbar) з усіма інструментами для редагування файлів.
|
||||||
|
|
||||||
## Map controls
|
## Керування картою
|
||||||
|
|
||||||
Finally, on the right side of the interface, you will find the [map controls](./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 file format
|
title: Формат GPX-файлу
|
||||||
---
|
---
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -8,27 +8,27 @@ title: GPX file format
|
|||||||
|
|
||||||
# { title }
|
# { title }
|
||||||
|
|
||||||
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.
|
<a href="https://www.topografix.com/gpx.asp" target="_blank">Формат GPX-файлу</a> це відкритий стандарт для обміну GPS-даними між застосунками та GPS-пристроями.
|
||||||
It essentially consists of a series of GPS points encoding one or multiple GPS traces, and, optionally, some points of interest.
|
По суті, він складається з набору GPS-точок, які описують один або кілька GPS-треків, а також, за бажанням, точки інтересу.
|
||||||
|
|
||||||
GPX files may also contain metadata, of which the **name** and **description** fields are the most useful for users.
|
GPX-файли також можуть містити метадані, серед яких для користувачів найкорисніші поля **назва** та **опис**.
|
||||||
|
|
||||||
### <Waypoints size="16" class="inline-block" style="margin-bottom: 2px" /> Tracks, segments, and GPS points
|
### <Waypoints size="16" class="inline-block" style="margin-bottom: 2px" /> Треки, сегменти та GPS-точки
|
||||||
|
|
||||||
As mentioned above, a GPX file can contain multiple GPS traces.
|
Як згадано вище, GPX-файл може містити кілька GPS-треків.
|
||||||
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**.
|
Крім того, він може містити метадані, такі як **назва**, **опис** і **властивості вигляду**.
|
||||||
- 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.
|
- **GPS-точка** — це місце з широтою, довготою, також додатково часовою міткою й висотою.
|
||||||
Some devices also store additional information such as heart rate, cadence, temperature, and power.
|
Деякі пристрої також зберігають додаткову інформацію, такі як пульс, каденс, температуру та потужність.
|
||||||
|
|
||||||
In most cases, GPX files contain a single track with a single segment.
|
У більшості випадків GPX-файли містять один трек з одним сегментом.
|
||||||
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" /> Points of interest
|
### <MapPin size="16" class="inline-block" style="margin-bottom: 2px" /> Точки інтересу
|
||||||
|
|
||||||
**Points of interest** (technically called _waypoints_) represent locations of interest to show either on a GPS device or on a digital map.
|
**Точки інтересу** (технічно вони називаються **waypoints**) позначають цікаві місця, які можна показувати на GPS-пристрої або цифровій карті.
|
||||||
|
|
||||||
In addition to its coordinates, a point of interest can have a **name** and a **description**.
|
Окрім координат, точка інтересу може мати **назву** та **опис**.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Integration
|
title: Інтеграція
|
||||||
---
|
---
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -9,18 +9,18 @@ title: Integration
|
|||||||
|
|
||||||
# { title }
|
# { title }
|
||||||
|
|
||||||
You can use **gpx.studio** to create maps showing your GPX files and embed them in your website.
|
Ви можете використовувати **gpx.studio**, щоб створювати карти з вашими GPX-файлами та вбудовувати їх на свій сайт.
|
||||||
|
|
||||||
All you need is:
|
Все, що вам потрібно:
|
||||||
|
|
||||||
1. GPX files hosted on your server or on Google Drive, or accessible via a public URL;
|
1. GPX-файли, розміщені на вашому сервері чи Google Drive або доступні за публічною URL-адресою;
|
||||||
2. _Optional:_ a <a href="https://cloud.maptiler.com/auth/widget?next=https://cloud.maptiler.com/maps/" target="_blank">MapTiler key</a> to load MapTiler maps.
|
2. _Необов’язково:_ <a href="https://cloud.maptiler.com/auth/widget?next=https://cloud.maptiler.com/maps/" target="_blank">ключ MapTiler</a> для завантаження карт MapTiler.
|
||||||
|
|
||||||
You can then play with the configurator below to customize your map and generate the corresponding HTML code.
|
Після цього можна скористатися конфігуратором нижче, щоб налаштувати карту та згенерувати відповідний HTML-код.
|
||||||
|
|
||||||
<DocsNote type="warning">
|
<DocsNote type="warning">
|
||||||
|
|
||||||
You will need to set up <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" target="_blank">Cross-Origin Resource Sharing (CORS)</a> headers on your server to allow <b>gpx.studio</b> to load your GPX files.
|
На вашому сервері потрібно буде налаштувати заголовки <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" target="_blank">Cross-Origin Resource Sharing (CORS)</a>, щоб дозволити <b>gpx.studio</b> завантажувати ваші GPX-файли.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Map controls
|
title: Керування картою
|
||||||
---
|
---
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -10,63 +10,63 @@ title: Map controls
|
|||||||
|
|
||||||
# { title }
|
# { title }
|
||||||
|
|
||||||
The map controls are located on the right side of the interface.
|
Елементи керування картою розташовані в правій частині інтерфейсу.
|
||||||
These controls allow you to navigate the map, zoom in and out, and switch between different map styles.
|
Вони дають змогу переміщатися картою, наближати й віддаляти її, а також перемикатися між різними стилями карти.
|
||||||
|
|
||||||
### <Diff size="16" class="inline-block" style="margin-bottom: 2px" /> Map navigation
|
### <Diff size="16" class="inline-block" style="margin-bottom: 2px" /> Карта навігації
|
||||||
|
|
||||||
The controls at the top allow you to zoom in <Plus size="16" class="inline-block" style="margin-bottom: 2px" /> and out <Minus size="16" class="inline-block" style="margin-bottom: 2px" />, and to change the orientation and tilt of the map <Compass size="16" class="inline-block" style="margin-bottom: 2px" />.
|
Елементи керування вгорі дають змогу наближати <Plus size="16" class="inline-block" style="margin-bottom: 2px" /> і віддаляти <Minus size="16" class="inline-block" style="margin-bottom: 2px" /> карту, а також змінювати її орієнтацію та нахил <Compass size="16" class="inline-block" style="margin-bottom: 2px" />.
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
To control the orientation and tilt of the map, you can also drag the map while holding <kbd>Ctrl</kbd>.
|
Щоб керувати орієнтацією та нахилом карти, також можна перетягувати карту, утримуючи <kbd>Ctrl</kbd>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|
||||||
### <Search size="16" class="inline-block" style="margin-bottom: 2px" /> Search bar
|
### <Search size="16" class="inline-block" style="margin-bottom: 2px" /> Панель пошуку
|
||||||
|
|
||||||
You can use the search bar to look for an address and navigate to it on the map.
|
Рядок пошуку можна використовувати, щоб знайти адресу та перейти до неї на карті.
|
||||||
|
|
||||||
### <LocateFixed size="16" class="inline-block" style="margin-bottom: 2px" /> Locate button
|
### <LocateFixed size="16" class="inline-block" style="margin-bottom: 2px" /> Кнопка визначення місцезнаходження
|
||||||
|
|
||||||
The locate button centers the map on your current location.
|
Кнопка визначення місцезнаходження центрує карту на вашому поточному місці.
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
This only works if you have allowed your browser and <b>gpx.studio</b> to access your location.
|
Це працює лише тоді, коли ви дозволили браузеру та <b>gpx.studio</b> доступ до свого місцезнаходження.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|
||||||
### <PersonStanding size="16" class="inline-block" style="margin-bottom: 2px" /> Street view
|
### <PersonStanding size="16" class="inline-block" style="margin-bottom: 2px" /> Перегляд вулиць
|
||||||
|
|
||||||
This button can be used to enable street view mode on the map.
|
Ця кнопка вмикає режим перегляду вулиць на карті.
|
||||||
Depending on the street view source chosen in the [settings](./menu/settings), street view imagery can be accessed differently.
|
Залежно від джерела перегляду вулиць, вибраного в [налаштуваннях](./menu/settings), зображення перегляду вулиць відкриваються по-різному.
|
||||||
|
|
||||||
- <a href="https://www.mapillary.com/" target="_blank">Mapillary</a>: the street view coverage will appear as green lines on the map. When zoomed in enough, green dots will show the exact locations where street view imagery is available. Hovering over a green dot will show the street view image at that location.
|
- <a href="https://www.mapillary.com/" target="_blank">Mapillary</a>: покриття перегляду вулиць відображатиметься на карті зеленими лініями. За достатнього наближення зелені точки показуватимуть точні місця, де доступні зображення перегляду вулиць. Наведення на зелену точку покаже зображення перегляду вулиць у цьому місці.
|
||||||
- <a href="https://www.google.com/streetview/" target="_blank">Google Street View</a>: click on the map to open a new tab with the street view imagery at that location.
|
- <a href="https://www.google.com/streetview/" target="_blank">Google Street View</a>: клацніть на карті, щоб відкрити нову вкладку із зображенням перегляду вулиць у цьому місці.
|
||||||
|
|
||||||
### <Layers size="16" class="inline-block" style="margin-bottom: 2px" /> Map layers
|
### <Layers size="16" class="inline-block" style="margin-bottom: 2px" /> Шари карти
|
||||||
|
|
||||||
The map layers button allows you to switch between different basemaps, and toggle map overlays and categories of points of interest.
|
Кнопка шарів карти дає змогу перемикатися між різними базовими картами, а також показувати або сховати накладені шари карти й категорії точок інтересу.
|
||||||
|
|
||||||
- **Basemaps** are background maps that present the main geographic features of the world.
|
- **Базові карти** — це фонові карти, які показують основні географічні об’єкти світу.
|
||||||
Depending on their purpose, basemaps have different styles and levels of detail.
|
Залежно від призначення, базові карти мають різні стилі та рівні деталізації.
|
||||||
Only one basemap can be displayed at a time.
|
Одночасно може відображатися лише одна базова карта.
|
||||||
- **Overlays** are additional layers that can be displayed on top of the basemap to provide complementary information.
|
- **Накладені шари** — це додаткові шари, які можна відображати поверх базової карти для надання додаткової інформації.
|
||||||
- **Points of interest** can be added to the map to show different categories of places, such as shops, restaurants, or accommodations.
|
- **Точки інтересу** можна додавати на карту, щоб показувати різні категорії місць, наприклад магазини, ресторани або житло.
|
||||||
|
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center">
|
||||||
<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.
|
Наведіть курсор на карту, щоб показати накладений шар <a href="https://hiking.waymarkedtrails.org" target="_blank">пішохідних маршрутів Waymarked Trails</a> поверх топографічної базової карти.
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
A large collection of global and local basemaps and overlays is available in **gpx.studio**, as well as a selection of point-of-interest categories.
|
У **gpx.studio** доступна велика колекція глобальних і локальних базових карт та накладених шарів, а також добірка категорій точок інтересу.
|
||||||
They can be enabled in the [map layer settings dialog](./menu/settings).
|
Їх можна ввімкнути в діалоговому вікні [налаштувань шарів карти](./menu/settings).
|
||||||
|
|
||||||
In these settings, you can also manage the opacity of the overlays.
|
У цих налаштуваннях також можна керувати прозорістю накладених шарів.
|
||||||
|
|
||||||
For advanced users, it is possible to add custom basemaps and overlays by providing <a href="https://en.wikipedia.org/wiki/Web_Map_Tile_Service" target="_blank">WMTS</a>, <a href="https://en.wikipedia.org/wiki/Web_Map_Service" target="_blank">WMS</a>, or <a href="https://maplibre.org/maplibre-style-spec/" target="_blank">MapLibre style JSON</a> URLs.
|
Для досвідчених користувачів є можливість додавати власні базові карти та накладені шари, указавши URL-адреси <a href="https://en.wikipedia.org/wiki/Web_Map_Tile_Service" target="_blank">WMTS</a>, <a href="https://en.wikipedia.org/wiki/Web_Map_Service" target="_blank">WMS</a> або <a href="https://maplibre.org/maplibre-style-spec/" target="_blank">MapLibre JSON</a>.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Menu
|
title: Меню
|
||||||
---
|
---
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -8,10 +8,10 @@ title: Menu
|
|||||||
|
|
||||||
# { title }
|
# { title }
|
||||||
|
|
||||||
The main menu, located at the top of the interface, provides access to actions, options, and settings divided into several categories, explained separately in the following sections.
|
У верхній частині інтерфейсу розташоване головне меню. Воно дає доступ до дій, параметрів і налаштувань, поділених на кілька категорій, які описано нижче.
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Most of the menu actions can also be performed using the keyboard shortcuts displayed in the menu.
|
Для більшості дій у меню також доступні комбінації клавіш, які показано поруч із відповідними пунктами меню.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: File actions
|
title: Дії з файлом
|
||||||
---
|
---
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -9,41 +9,41 @@ title: File actions
|
|||||||
|
|
||||||
# { title }
|
# { title }
|
||||||
|
|
||||||
The file actions menu contains a set of pretty self-explanatory file operations.
|
Меню дій файлу містить набір доволі очевидних операцій із файлами.
|
||||||
|
|
||||||
### <Plus size="16" class="inline-block" style="margin-bottom: 2px" /> New
|
### <Plus size="16" class="inline-block" style="margin-bottom: 2px" /> Новий
|
||||||
|
|
||||||
Create a new empty file.
|
Створити новий порожній файл.
|
||||||
|
|
||||||
### <FolderOpen size="16" class="inline-block" style="margin-bottom: 2px" /> Open...
|
### <FolderOpen size="16" class="inline-block" style="margin-bottom: 2px" /> Відкрити...
|
||||||
|
|
||||||
Відкрити файли з комп'ютера.
|
Відкрити файли з комп'ютера.
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
You can also drag and drop files directly from your file system into the window.
|
Ви також можете перетягувати файли безпосередньо з файлової системи у вікно.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|
||||||
### <Copy size="16" class="inline-block" style="margin-bottom: 2px" /> Duplicate
|
### <Copy size="16" class="inline-block" style="margin-bottom: 2px" /> Дублювати
|
||||||
|
|
||||||
Create a copy of the currently selected files.
|
Створити копію обраних файлів.
|
||||||
|
|
||||||
### <FileX size="16" class="inline-block" style="margin-bottom: 2px" /> Delete
|
### <FileX size="16" class="inline-block" style="margin-bottom: 2px" /> Видалити
|
||||||
|
|
||||||
Delete the currently selected files.
|
Видалити обрані файли.
|
||||||
|
|
||||||
### <FileX size="16" class="inline-block" style="margin-bottom: 2px" /> Delete all
|
### <FileX size="16" class="inline-block" style="margin-bottom: 2px" /> Видалити все
|
||||||
|
|
||||||
Delete all files.
|
Видалити всі файли.
|
||||||
|
|
||||||
### <Download size="16" class="inline-block" style="margin-bottom: 2px" /> Export...
|
### <Download size="16" class="inline-block" style="margin-bottom: 2px" /> Експортувати...
|
||||||
|
|
||||||
Open the export dialog to save the currently selected files to your computer.
|
Відкрийте діалогове вікно експорту, щоб зберегти поточні обрані файли на ваш комп'ютер.
|
||||||
|
|
||||||
### <Download size="16" class="inline-block" style="margin-bottom: 2px" /> Export all...
|
### <Download size="16" class="inline-block" style="margin-bottom: 2px" /> Експортувати все...
|
||||||
|
|
||||||
Open the export dialog to save all files to your computer.
|
Відкрийте діалог експорту для збереження всіх файлів на ваш комп'ютер.
|
||||||
|
|
||||||
<DocsNote type="warning">
|
<DocsNote type="warning">
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Settings
|
title: Налаштування
|
||||||
---
|
---
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -9,22 +9,22 @@ title: Settings
|
|||||||
|
|
||||||
# { title }
|
# { title }
|
||||||
|
|
||||||
### <Ruler size="16" class="inline-block" style="margin-bottom: 2px" /> Distance units
|
### <Ruler size="16" class="inline-block" style="margin-bottom: 2px" /> Одиниці відстані
|
||||||
|
|
||||||
Change the units used to display distances in the interface.
|
Змінити одиниці виміру для відображення відстаней в інтерфейсі.
|
||||||
|
|
||||||
### <Zap size="16" class="inline-block" style="margin-bottom: 2px" /> Velocity units
|
### <Zap size="16" class="inline-block" style="margin-bottom: 2px" /> Одиниці швидкості
|
||||||
|
|
||||||
Change the units used to display velocities in the interface.
|
Змінити одиниці виміру для відображення швидкостей в інтерфейсі.
|
||||||
You can choose between distance per hour or minutes per distance, which can be more suitable for running activities.
|
Ви можете вибрати між відстанню за годину або хвилинами на одиницю відстані, що може бути зручнішим для бігових активностей.
|
||||||
|
|
||||||
### <Thermometer size="16" class="inline-block" style="margin-bottom: 2px" /> Temperature units
|
### <Thermometer size="16" class="inline-block" style="margin-bottom: 2px" /> Одиниці температури
|
||||||
|
|
||||||
Change the units used to display temperatures in the interface.
|
Змінити одиниці виміру для відображення температур в інтерфейсі.
|
||||||
|
|
||||||
### <Languages size="16" class="inline-block" style="margin-bottom: 2px" /> Language
|
### <Languages size="16" class="inline-block" style="margin-bottom: 2px" /> Мова
|
||||||
|
|
||||||
Change the language used in the interface.
|
Змінити мову, яка використовується в інтерфейсі.
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
@@ -34,17 +34,17 @@ Change the language used in the interface.
|
|||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|
||||||
### <Sun size="16" class="inline-block" style="margin-bottom: 2px" /> Theme
|
### <Sun size="16" class="inline-block" style="margin-bottom: 2px" /> Тема
|
||||||
|
|
||||||
Change the theme used in the interface.
|
Змінити тему, яка використана в інтерфейсі.
|
||||||
|
|
||||||
### <PersonStanding size="16" class="inline-block" style="margin-bottom: 2px" /> Street view source
|
### <PersonStanding size="16" class="inline-block" style="margin-bottom: 2px" /> Джерело перегляду вулиці
|
||||||
|
|
||||||
Change the source used for the [street view control](../map-controls).
|
Змінити джерело, що використовується для [панелі перегляду вулиці](../map-controls).
|
||||||
The default one is <a href="https://www.mapillary.com" target="_blank">Mapillary</a>, but you can also use <a href="https://www.google.com/streetview/" target="_blank">Google Street View</a>.
|
За замовчуванням використовується <a href="https://www.mapillary.com" target="_blank">Mapillary</a>, але ви також можете скористатися <a href="https://www.google.com/streetview/" target="_blank">Google Street View</a>.
|
||||||
Learn more about how to use the street view control in the [map controls section](../map-controls).
|
Дізнатися більше про те, як використовувати контроль над вулицею в [панелі перегляду вулиці](../map-controls).
|
||||||
|
|
||||||
### <Layers size="16" class="inline-block" style="margin-bottom: 2px" /> Map layers...
|
### <Layers size="16" class="inline-block" style="margin-bottom: 2px" /> Шари мапи...
|
||||||
|
|
||||||
Open a dialog where you can enable or disable map layers, add custom ones, change the opacity of overlays, and more.
|
Відкрити діалог налаштування шарів: вмикання/вимикання, додавання власних, регулювання прозорості накладень та інше.
|
||||||
More information about map layers can be found in the [map controls section](../map-controls).
|
Детальну інформацію про шари карти можна знайти в [розділі керування картою](../map-controls).
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: View options
|
title: Параметри виду
|
||||||
---
|
---
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -9,46 +9,46 @@ title: View options
|
|||||||
|
|
||||||
# { title }
|
# { title }
|
||||||
|
|
||||||
This menu provides options to rearrange the interface and the map view.
|
Це меню надає можливість налаштовувати інтерфейс та вигляд карти.
|
||||||
|
|
||||||
### <ChartArea size="16" class="inline-block" style="margin-bottom: 2px" /> Elevation profile
|
### <ChartArea size="16" class="inline-block" style="margin-bottom: 2px" /> Профіль висоти
|
||||||
|
|
||||||
Hide the elevation profile to make room for the map, or show it to inspect the current selection.
|
Приховати графік висоти, щоб звільнити більше місця для карти, або відобразіть його, щоб дослідити вибрану ділянку.
|
||||||
|
|
||||||
### <ListTree size="16" class="inline-block" style="margin-bottom: 2px" /> File tree
|
### <ListTree size="16" class="inline-block" style="margin-bottom: 2px" /> Дерево файлів
|
||||||
|
|
||||||
Toggle the tree layout for the [file list](../files-and-stats).
|
Показати або сховати [дерево файлів](../files-and-stats).
|
||||||
Ця схема ідеально підходить для роботи з великою кількістю відкритих файлів, оскільки вони розміщуються у вигляді вертикального списку в правій частині екрана.
|
Ця схема ідеально підходить для роботи з великою кількістю відкритих файлів, оскільки вони розміщуються у вигляді вертикального списку в правій частині екрана.
|
||||||
In addition, the file tree view enables you to inspect the [tracks, segments, and points of interest](../gpx) contained inside the files through collapsible sections.
|
Також дерево файлів дає змогу переглядати [треки, сегменти та точки інтересу](../gpx), що містяться всередині файлів, у згортних розділах.
|
||||||
|
|
||||||
### <Map size="16" class="inline-block" style="margin-bottom: 2px" /> Switch to previous basemap
|
### <Map size="16" class="inline-block" style="margin-bottom: 2px" /> Перемкнутися на попередню базову карту
|
||||||
|
|
||||||
Change the basemap to the one previously selected through the [map layer control](../map-controls).
|
Перемкнути базову карту на попередньо вибрану через [керування шарами карти](../map-controls).
|
||||||
|
|
||||||
### <Layers2 size="16" class="inline-block" style="margin-bottom: 2px" /> Toggle overlays
|
### <Layers2 size="16" class="inline-block" style="margin-bottom: 2px" /> Перемкнути накладені шари
|
||||||
|
|
||||||
Toggle the visibility of the map overlays selected through the [map layer control](../map-controls).
|
Перемкнути видимість накладених шарів карти, вибраних через [керування шарами карти](../map-controls).
|
||||||
|
|
||||||
### <Coins size="16" class="inline-block" style="margin-bottom: 2px" /> Distance markers
|
### <Coins size="16" class="inline-block" style="margin-bottom: 2px" /> Позначки відстані
|
||||||
|
|
||||||
Toggle the visibility of distance markers on the map.
|
Перемкнути видимість позначок відстані на карті.
|
||||||
They are displayed for the current selection, like the [elevation profile](../files-and-stats).
|
Позначки відстані відображаються для поточного виділення, як і [профіль висоти](../files-and-stats).
|
||||||
|
|
||||||
### <Milestone size="16" class="inline-block" style="margin-bottom: 2px" /> Direction arrows
|
### <Milestone size="16" class="inline-block" style="margin-bottom: 2px" /> Стрілки напрямку
|
||||||
|
|
||||||
Toggle the visibility of direction arrows on the map.
|
Перемкнути видимість стрілок напрямку.
|
||||||
|
|
||||||
### <Box size="16" class="inline-block" style="margin-bottom: 2px" /> Toggle 3D
|
### <Box size="16" class="inline-block" style="margin-bottom: 2px" /> Перемкнути 3D
|
||||||
|
|
||||||
Enter or exit the 3D map view.
|
Увімкнути або вимкнути режим 3D-карти.
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
To control the orientation and tilt of the map, you can also drag the map while holding <kbd>Ctrl</kbd>.
|
Щоб керувати орієнтацією та нахилом карти, також можна перетягувати карту, утримуючи <kbd>Ctrl</kbd>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|
||||||
### <Maximize2 size="16" class="inline-block" style="margin-bottom: 2px" /> Full screen
|
### <Maximize2 size="16" class="inline-block" style="margin-bottom: 2px" /> Повноекранний режим
|
||||||
|
|
||||||
Enter or exit full screen mode.
|
Увійти або вийти з повноекранного режиму.
|
||||||
You can also press <kbd>F11</kbd> to toggle, or <kbd>Escape</kbd> to exit.
|
Ви також можете натиснути <kbd>F11</kbd>, щоб перемкнути режим, або <kbd>Escape</kbd>, щоб вийти.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Toolbar
|
title: Панель інструментів
|
||||||
---
|
---
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -18,8 +18,8 @@ title: Toolbar
|
|||||||
|
|
||||||
# { title }
|
# { title }
|
||||||
|
|
||||||
The toolbar is located on the left side of the map and is the heart of the application, as it provides access to the main features of **gpx.studio**.
|
Панель інструментів розташована ліворуч від карти та є серцем застосунку, адже надає доступ до основних можливостей **gpx.studio**.
|
||||||
Each tool is represented by an icon and can be activated by clicking on it.
|
Кожен інструмент має значок, за якою його можна активувати.
|
||||||
|
|
||||||
<div class="flex flex-row justify-center text-foreground">
|
<div class="flex flex-row justify-center text-foreground">
|
||||||
<div>
|
<div>
|
||||||
@@ -27,6 +27,6 @@ Each tool is represented by an icon and can be activated by clicking on it.
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
As with [edit actions](./menu/edit), most tools can be applied to multiple files at once and to [inner tracks and segments](./gpx).
|
Як і [дії редагування](./menu/edit), більшість інструментів можна застосовувати одразу до кількох файлів, а також до [вкладених треків і сегментів](./gpx).
|
||||||
|
|
||||||
The next sections describe each tool in detail.
|
У наступних розділах кожен інструмент описано докладно.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Clean
|
title: Очищення
|
||||||
---
|
---
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -9,9 +9,9 @@ title: Clean
|
|||||||
|
|
||||||
# <SquareDashedMousePointer size="24" class="inline-block" style="margin-bottom: 5px" /> { title }
|
# <SquareDashedMousePointer size="24" class="inline-block" style="margin-bottom: 5px" /> { title }
|
||||||
|
|
||||||
When the clean tool is selected, dragging the map will create a rectangular selection.
|
Коли вибрано інструмент очистити, перетягуванням на карті можна створити прямокутне виділення.
|
||||||
|
|
||||||
Depending on the options selected in the dialog shown below, clicking the delete button will remove GPS points and/or [points of interest](../gpx) located either inside or outside the selection.
|
Залежно від параметрів, вибраних у показаному нижче діалоговому вікні, натискання кнопки видалення прибере GPS-точки та/або [точки інтересу](../gpx), розташовані всередині або поза межами виділення.
|
||||||
|
|
||||||
<div class="flex flex-row justify-center">
|
<div class="flex flex-row justify-center">
|
||||||
<Clean class="text-foreground p-3 border rounded-md shadow-lg" />
|
<Clean class="text-foreground p-3 border rounded-md shadow-lg" />
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Elevation
|
title: Висота
|
||||||
---
|
---
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -10,7 +10,7 @@ title: Elevation
|
|||||||
|
|
||||||
# <MountainSnow size="24" class="inline-block" style="margin-bottom: 5px" /> { title }
|
# <MountainSnow size="24" class="inline-block" style="margin-bottom: 5px" /> { title }
|
||||||
|
|
||||||
This tool allows you to add elevation data to traces and [points of interest](../gpx), or to replace the existing data.
|
Цей інструмент дає змогу додати дані висоти до треків і [точок інтересу](../gpx) або замінити наявні дані.
|
||||||
|
|
||||||
<div class="flex flex-row justify-center">
|
<div class="flex flex-row justify-center">
|
||||||
<Elevation class="text-foreground p-3 border rounded-md shadow-lg" />
|
<Elevation class="text-foreground p-3 border rounded-md shadow-lg" />
|
||||||
@@ -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>.
|
Дані висоти надає <a href="https://mapterhorn.com" target="_blank">Mapterhorn</a>.
|
||||||
You can learn more about its origin and accuracy in the <a href="https://mapterhorn.com/attribution/" target="_blank">documentation</a>.
|
Докладніше про походження цих даних і їхню точність можна дізнатися в <a href="https://mapterhorn.com/attribution/" target="_blank">документації</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Extract
|
title: Виокремлення
|
||||||
---
|
---
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -10,17 +10,17 @@ title: Extract
|
|||||||
|
|
||||||
# <Ungroup size="24" class="inline-block" style="margin-bottom: 5px" /> { title }
|
# <Ungroup size="24" class="inline-block" style="margin-bottom: 5px" /> { title }
|
||||||
|
|
||||||
This tool allows you to extract [tracks (or segments)](../gpx) from files (or tracks) containing multiple of them.
|
Цей інструмент дає змогу виокремити [треки (або сегменти)](../gpx) з файлів (або треків), у яких міститься кілька таких елементів.
|
||||||
|
|
||||||
<div class="flex flex-row justify-center">
|
<div class="flex flex-row justify-center">
|
||||||
<Extract class="text-foreground p-3 border rounded-md shadow-lg" />
|
<Extract class="text-foreground p-3 border rounded-md shadow-lg" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
Applying the tool to a file containing multiple tracks will create a new file for each of the tracks it contains.
|
Якщо застосувати інструмент до файлу, який містить кілька треків, для кожного з них буде створено окремий файл.
|
||||||
Similarly, applying the tool to a track containing multiple segments will create (in the same file) a new track for each of the segments it contains.
|
Так само, якщо застосувати інструмент до треку, який містить кілька сегментів, буде створено новий трек (у тому самому файлі) для кожного з цих сегментів.
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
When extracting the tracks from a file containing <a href="../gpx">points of interest</a>, the tool will automatically assign each point of interest to the track it is closest to.
|
Під час виокремлення треків із файлу, що містить <a href="../gpx">точки інтересу</a>, інструмент автоматично призначить кожну точку інтересу до найближчого до неї треку.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Merge
|
title: Об’єднання
|
||||||
---
|
---
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -10,16 +10,16 @@ title: Merge
|
|||||||
|
|
||||||
# <Group size="24" class="inline-block" style="margin-bottom: 5px" /> { title }
|
# <Group size="24" class="inline-block" style="margin-bottom: 5px" /> { title }
|
||||||
|
|
||||||
To use this tool, you need to [select](../files-and-stats) multiple files, [tracks, or segments](../gpx).
|
Щоб скористатися цим інструментом, потрібно [вибрати](../files-and-stats) кілька файлів, [треків або сегментів](../gpx).
|
||||||
|
|
||||||
- If your goal is to create a single continuous trace from your selection, use the **Connect the traces** option and validate.
|
- Якщо потрібно створити один суцільний трек із вибраного, виберіть параметр **З’єднати треки** та підтвердьте.
|
||||||
- The second option can be used to create or manage files with multiple [tracks or segments](../gpx).
|
- Другий параметр дає змогу створювати та керувати файлами з кількома [треками або сегментами](../gpx).
|
||||||
Merging files (or tracks) will result in a single file (or track) containing all tracks (or segments) from the selection.
|
Після об’єднання файлів (або треків) буде створено один файл (або трек), який міститиме всі вибрані треки (або сегменти).
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
Selected items are merged in the order they appear in the files list.
|
Вибрані елементи об’єднуються в тому порядку, у якому вони відображаються у списку файлів.
|
||||||
Reorder items by drag-and-drop if needed.
|
За потреби змініть порядок елементів перетягуванням.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Minify
|
title: Зменшення
|
||||||
---
|
---
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -10,9 +10,9 @@ title: Minify
|
|||||||
|
|
||||||
# <Funnel size="24" class="inline-block" style="margin-bottom: 5px" /> { title }
|
# <Funnel size="24" class="inline-block" style="margin-bottom: 5px" /> { title }
|
||||||
|
|
||||||
This tool can be used to reduce the number of GPS points in a trace, which can be useful for decreasing its size.
|
Цей інструмент дає змогу зменшити кількість GPS-точок у треку, що допомагає зменшити розмір файлу.
|
||||||
|
|
||||||
You can adjust the tolerance of the simplification algorithm using the slider, and see the number of points that will be kept, as well as the simplified trace on the map.
|
За допомогою повзунка можна налаштувати рівень спрощення, а також побачити кількість точок, які буде збережено, і спрощений трек на карті.
|
||||||
|
|
||||||
<div class="flex flex-row justify-center">
|
<div class="flex flex-row justify-center">
|
||||||
<Reduce class="text-foreground p-3 border rounded-md shadow-lg" />
|
<Reduce class="text-foreground p-3 border rounded-md shadow-lg" />
|
||||||
@@ -20,7 +20,7 @@ You can adjust the tolerance of the simplification algorithm using the slider, a
|
|||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
The tolerance value represents the maximum distance allowed between the original trace and the simplified trace.
|
Рівень спрощення визначає максимальне допустиме відхилення спрощеного треку від оригінального.
|
||||||
You can read more about the algorithm used <a href="https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm" target="_blank">here</a>.
|
Докладніше про алгоритм спрощення можна прочитати <a href="https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm" target="_blank">тут</a>.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Points of interest
|
title: Точки інтересу
|
||||||
---
|
---
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -9,19 +9,19 @@ title: Points of interest
|
|||||||
|
|
||||||
# <MapPin size="24" class="inline-block" style="margin-bottom: 5px" /> { title }
|
# <MapPin size="24" class="inline-block" style="margin-bottom: 5px" /> { title }
|
||||||
|
|
||||||
[Points of interest](../gpx) can be added to GPX files to mark locations of interest on the map and display them on your GPS device.
|
Точки інтересу(../gpx) можна додавати до GPX-файлів, щоб позначати цікаві місця на карті та відображати їх на GPS-пристрої.
|
||||||
|
|
||||||
### Creating a point of interest
|
### Створити точку інтересу
|
||||||
|
|
||||||
To create a point of interest, fill in the form shown below.
|
Щоб додати точку інтересу, заповніть форму нижче.
|
||||||
You can choose the location of the point of interest either by clicking on the map or by entering the coordinates manually.
|
Щоб указати розташування точки інтересу, клацніть на карті або введіть координати вручну.
|
||||||
Validate the form when you are done.
|
Після заповнення збережіть форму.
|
||||||
|
|
||||||
<div class="flex flex-row justify-center">
|
<div class="flex flex-row justify-center">
|
||||||
<Waypoint class="text-foreground p-3 border rounded-md shadow-lg" />
|
<Waypoint class="text-foreground p-3 border rounded-md shadow-lg" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
### Editing a point of interest
|
### Редагування точки інтересу
|
||||||
|
|
||||||
The form above can also be used to edit an existing point of interest after selecting it on the map.
|
Форму вище також можна використовувати для редагування наявної точки інтересу після її вибору на карті.
|
||||||
If you only need to move the point of interest, you can drag it to the desired location.
|
Якщо потрібно лише перемістити точку інтересу, перетягніть її в потрібне місце.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Route planning and editing
|
title: Планування та редагування маршруту
|
||||||
---
|
---
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -11,74 +11,74 @@ title: Route planning and editing
|
|||||||
|
|
||||||
# <Pencil size="24" class="inline-block" style="margin-bottom: 5px" /> { title }
|
# <Pencil size="24" class="inline-block" style="margin-bottom: 5px" /> { title }
|
||||||
|
|
||||||
The route planning and editing tool allows you to create and edit routes by placing or moving anchor points on the map.
|
Інструмент планування та редагування маршруту дає змогу створювати й редагувати маршрути, розміщуючи або переміщуючи точки на карті.
|
||||||
|
|
||||||
## Settings
|
## Налаштування
|
||||||
|
|
||||||
As shown below, the tool dialog contains a few settings to control the routing behavior.
|
Як показано нижче, діалогове вікно інструмент містить кілька параметрів, які можна контролювати поведінку побудови маршруту.
|
||||||
You can minimize the dialog to save space by clicking on <button><SquareArrowUpLeft size="16" class="inline-block" style="margin-bottom: 2px" /></button>.
|
Щоб звільнити місце, діалогове вікно можна згорнути, натиснувши <button><SquareArrowUpLeft size="16" class="inline-block" style="margin-bottom: 2px" /></button>.
|
||||||
|
|
||||||
<div class="flex flex-row justify-center">
|
<div class="flex flex-row justify-center">
|
||||||
<Routing minimizable={false} class="text-foreground p-3 border rounded-md shadow-lg" />
|
<Routing minimizable={false} class="text-foreground p-3 border rounded-md shadow-lg" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
### <Route size="16" class="inline-block" style="margin-bottom: 2px" /> Routing
|
### <Route size="16" class="inline-block" style="margin-bottom: 2px" /> Побудова маршруту
|
||||||
|
|
||||||
When routing is enabled, anchor points placed or moved on the map will be connected by a route calculated on the <a href="https://www.openstreetmap.org" target="_blank">OpenStreetMap</a> road network.
|
Якщо побудову маршруту ввімкнено, точки, які ви розміщуєте або переміщуєте на карті, з’єднуються маршрутом, розрахованим за дорожньою мережею <a href="https://www.openstreetmap.org" target="_blank">OpenStreetMap</a>.
|
||||||
Disable routing to connect anchor points with straight lines.
|
Вимкніть побудову маршруту, щоб з’єднувати точки прямими лініями.
|
||||||
This setting can also be toggled by pressing <kbd>F5</kbd>.
|
Це налаштування також можна перемкнути, натиснувши <kbd>F5</kbd>.
|
||||||
|
|
||||||
### <Bike size="16" class="inline-block" style="margin-bottom: 2px" /> Activity
|
### <Bike size="16" class="inline-block" style="margin-bottom: 2px" /> Активність
|
||||||
|
|
||||||
Select the activity type to tailor the routes for.
|
Виберіть тип активності, для якої прокладати маршрути.
|
||||||
|
|
||||||
### <TriangleAlert size="16" class="inline-block" style="margin-bottom: 2px" /> Allow private roads
|
### <TriangleAlert size="16" class="inline-block" style="margin-bottom: 2px" /> Дозволити приватні дороги
|
||||||
|
|
||||||
When enabled, the routing engine will consider private roads when computing routes.
|
Якщо цей параметр увімкнено, приватні дороги враховуватимуться під час побудови маршрутів.
|
||||||
|
|
||||||
<DocsNote type="warning">
|
<DocsNote type="warning">
|
||||||
|
|
||||||
Only use this option if you have local knowledge of the area and have permission to use the roads in question.
|
Використовуйте цей параметр лише тоді, коли добре знаєте місцевість і маєте дозвіл користуватися відповідними дорогами.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|
||||||
## Plotting and editing routes
|
## Прокладання та редагування маршрутів
|
||||||
|
|
||||||
Creating a route or extending an existing one is as simple as clicking on the map to place a new anchor point.
|
Щоб створити маршрут або продовжити наявний, достатньо клацнути на карті й додати нову точку.
|
||||||
|
|
||||||
You can also drag an existing anchor point to reroute the segment connecting it with the previous and next anchor point.
|
Наявну точку також можна перетягнути, щоб перебудувати сегмент між нею та попередньою і наступною точками.
|
||||||
|
|
||||||
Furthermore, new anchor points can be inserted between existing ones by hovering over the segment connecting them and dragging the anchor point that appears to the desired location.
|
Нові точки також можна додавати між наявними: наведіть курсор на сегмент, який їх з’єднує, і перетягніть точку, що з’явиться, у потрібне місце.
|
||||||
On touch devices, you can tap on the segment to insert a new anchor point.
|
На пристроях із сенсорним екраном торкніться сегмента, щоб вставити нову точку.
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
When editing imported GPX files, an initial set of anchor points is created automatically.
|
Під час редагування імпортованих GPX-файлів початковий набір точок створюється автоматично.
|
||||||
To ease the editing process, the more the map is zoomed in, the more anchor points are displayed.
|
Щоб полегшити редагування, що більше наближено карту, то більше точок відображається.
|
||||||
This allows the route to be edited at different levels of detail.
|
Завдяки цьому маршрут можна редагувати з різною деталізацією.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|
||||||
Finally, you can delete anchor points by clicking on them and selecting <button><Trash2 size="16" class="inline-block" style="margin-bottom: 4px" /> Delete</button> from the context menu.
|
Нарешті, щоб видалити точку, клацніть на неї та виберіть <button><Trash2 size="16" class="inline-block" style="margin-bottom: 4px" /> Видалити</button> у контекстному меню.
|
||||||
|
|
||||||
<DocsImage src="tools/routing" alt="Anchor points allow you to easily edit a route." />
|
<DocsImage src="tools/routing" alt="Опорні точки спрощують редагування маршруту." />
|
||||||
|
|
||||||
## Additional tools
|
## Додаткові інструменти
|
||||||
|
|
||||||
The following tools automate some common route modification operations.
|
Інструменти нижче автоматизують деякі типові дії з редагування маршруту.
|
||||||
|
|
||||||
### <ArrowRightLeft size="16" class="inline-block" style="margin-bottom: 2px" /> Reverse
|
### <ArrowRightLeft size="16" class="inline-block" style="margin-bottom: 2px" /> Розвернути
|
||||||
|
|
||||||
Reverse the direction of the route.
|
Змінити напрямок маршруту.
|
||||||
|
|
||||||
### <House size="16" class="inline-block" style="margin-bottom: 2px" /> Back to start
|
### <House size="16" class="inline-block" style="margin-bottom: 2px" /> До початку маршруту
|
||||||
|
|
||||||
Connect the last point of the route with the starting point, using the chosen routing settings.
|
Замкнути маршрут до початкової точки з урахуванням вибраних налаштувань побудови маршруту.
|
||||||
|
|
||||||
### <Repeat size="16" class="inline-block" style="margin-bottom: 2px" /> Round trip
|
### <Repeat size="16" class="inline-block" style="margin-bottom: 2px" /> Маршрут туди й назад
|
||||||
|
|
||||||
Return to the starting point by the same route.
|
Повернутися до старту тим самим маршрутом.
|
||||||
|
|
||||||
### <CirclePlay size="16" class="inline-block" style="margin-bottom: 2px" /> Change the start of the loop
|
### <CirclePlay size="16" class="inline-block" style="margin-bottom: 2px" /> Змінити початкову точку кільцевого маршруту
|
||||||
|
|
||||||
When the end point of the route is close enough to the start, you can change the start of the loop by clicking on any anchor point and selecting <button><CirclePlay size="16" class="inline-block" style="margin-bottom: 2px" /> Start loop here</button> from the context menu.
|
Коли кінцева точка маршруту достатньо близько до початкової, можна змінити початок кільцевого маршруту: клацніть будь-яку точку й виберіть <button><CirclePlay size="16" class="inline-block" style="margin-bottom: 2px" /> Почати кільцевий маршрут тут</button> у контекстному меню.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Crop and split
|
title: Обрізання та розділення
|
||||||
---
|
---
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -10,23 +10,23 @@ title: Crop and split
|
|||||||
|
|
||||||
# <ScissorsIcon size="24" class="inline-block" style="margin-bottom: 5px" /> { title }
|
# <ScissorsIcon size="24" class="inline-block" style="margin-bottom: 5px" /> { title }
|
||||||
|
|
||||||
## Crop
|
## Обрізання
|
||||||
|
|
||||||
Using the slider, you can define the part of the selected trace that you want to keep.
|
За допомогою повзунка можна визначити частину вибраного треку, яку потрібно залишити.
|
||||||
The start and end markers on the map and the [statistics and elevation profile](../files-and-stats) are updated in real time to reflect the selection.
|
Початкова й кінцева позначки на карті, а також [статистика та профіль висоти](../files-and-stats) оновлюються в реальному часі відповідно до вибраної частини.
|
||||||
Alternatively, you can drag a selection rectangle directly on the elevation profile.
|
Також можна виділити потрібну частину, перетягнувши прямокутник безпосередньо на профілі висоти.
|
||||||
Validate the selection when you are satisfied with the result.
|
Коли результат вас влаштовує, підтвердьте вибір.
|
||||||
|
|
||||||
<div class="flex flex-row justify-center">
|
<div class="flex flex-row justify-center">
|
||||||
<Scissors class="text-foreground p-3 border rounded-md shadow-lg" />
|
<Scissors class="text-foreground p-3 border rounded-md shadow-lg" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## Split
|
## Розділення
|
||||||
|
|
||||||
To split the selected trace into two parts, click on one of the split markers displayed along the trace.
|
Щоб розділити вибраний трек на дві частини, клацніть одну з позначок розділення, показаних уздовж треку.
|
||||||
To split at a specific point of your choice, hover over the trace on the map.
|
Щоб розділити трек у потрібному місці, наведіть курсор на трек на карті.
|
||||||
Scissors will appear at the cursor position, showing that you can split the trace at that point.
|
На місці курсора з’явиться значок ножиць, який вказує, що тут можна розділити трек.
|
||||||
|
|
||||||
You can choose to split the trace into two GPX files, or to keep the split parts in the same file as [tracks or segments](../gpx).
|
Ви можете розділити трек на два GPX-файли або залишити розділені частини в тому самому файлі як [треки чи сегменти](../gpx).
|
||||||
|
|
||||||
<DocsImage src="tools/split" alt="Hovering over the selected trace turns your cursor into scissors." />
|
<DocsImage src="tools/split" alt="При наведенні на вибраний трек курсор змінюється на значок ножиць." />
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Time
|
title: Час
|
||||||
---
|
---
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -10,18 +10,18 @@ title: Time
|
|||||||
|
|
||||||
# <CalendarClock size="24" class="inline-block" style="margin-bottom: 5px" /> { title }
|
# <CalendarClock size="24" class="inline-block" style="margin-bottom: 5px" /> { title }
|
||||||
|
|
||||||
This tool allows you to change or add timestamps to a trace.
|
Цей інструмент дає змогу змінювати або додавати часові мітки до треку.
|
||||||
You simply need to use the form shown below and validate it when you are done.
|
Достатньо заповнити форму нижче й підтвердити її після завершення.
|
||||||
|
|
||||||
<div class="flex flex-row justify-center">
|
<div class="flex flex-row justify-center">
|
||||||
<Time class="text-foreground p-3 border rounded-md shadow-lg" />
|
<Time class="text-foreground p-3 border rounded-md shadow-lg" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
When you edit the speed, the moving time is adapted accordingly in the form, and vice versa.
|
Коли ви змінюєте швидкість, час руху у формі відповідно оновлюється, і навпаки.
|
||||||
Similarly, when you edit the start time, the end time is updated to keep the same total duration, and vice versa.
|
Аналогічно, під час зміни часу початку час завершення оновлюється, щоб загальна тривалість залишалася незмінною, і навпаки.
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
When using this tool with existing timestamps, changing the time or speed will simply shift, stretch, or compress them accordingly.
|
Якщо в треку вже є часові мітки, зміна часу або швидкості лише зсуне, розтягне чи стисне їх відповідно.
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: FAQ
|
title: 常見問題
|
||||||
---
|
---
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -8,7 +8,7 @@ title: FAQ
|
|||||||
|
|
||||||
# { title }
|
# { title }
|
||||||
|
|
||||||
### Do I need to donate to use the website?
|
### 需要捐贈才能使用這網站嗎?
|
||||||
|
|
||||||
No.
|
No.
|
||||||
The website is free to use and always will be (as long as it is financially sustainable).
|
The website is free to use and always will be (as long as it is financially sustainable).
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Files and statistics
|
title: 檔案和統計
|
||||||
---
|
---
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -19,7 +19,7 @@ title: Files and statistics
|
|||||||
|
|
||||||
# { title }
|
# { title }
|
||||||
|
|
||||||
## File list
|
## 檔案列表
|
||||||
|
|
||||||
Once you have [opened](./menu/file) files, they will be shown as tabs in the file list located at the bottom of the map.
|
Once you have [opened](./menu/file) files, they will be shown as tabs in the file list located at the bottom of the map.
|
||||||
You can reorder them by dragging and dropping the tabs.
|
You can reorder them by dragging and dropping the tabs.
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ Before we dive into the details of each section, let's have a quick overview of
|
|||||||
At the top of the interface, you will find the [main 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.
|
This is where you can access common actions such as opening, closing, and exporting files, undoing and redoing actions, and adjusting the application settings.
|
||||||
|
|
||||||
## Files and statistics
|
## 檔案和統計
|
||||||
|
|
||||||
At the bottom of the interface, you will find the list of files currently open in the application.
|
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.
|
You can click on a file to select it and display its statistics below the list.
|
||||||
|
|||||||
@@ -10,87 +10,87 @@ title: Edit actions
|
|||||||
# { title }
|
# { title }
|
||||||
|
|
||||||
與文件操作不同,編輯操作可能會修改目前選定文件的內容。
|
與文件操作不同,編輯操作可能會修改目前選定文件的內容。
|
||||||
Moreover, when the tree layout of the files list is enabled (see [Files and statistics](../files-and-stats)), they can also be applied to [tracks, segments, and points of interest](../gpx).
|
若啟用檔案 [樹形佈局](../files-and-stats),操作也可作用於相關 [軌跡、路段和興趣點](../gpx)。
|
||||||
Therefore, we will refer to the elements that can be modified by these actions as _file items_.
|
在文件中,所有可通過以上操作修改的項目被稱為 _檔案項_。
|
||||||
Note that except for the undo and redo actions, the edit actions are also accessible through the context menu (right-click) of the file items.
|
注意,除復原和重做外,其餘操作也可通過右鍵點選檔案項來喚出操作菜單。
|
||||||
|
|
||||||
### <Undo2 size="16" class="inline-block" style="margin-bottom: 2px" /><Redo2 size="16" class="inline-block" style="margin-bottom: 2px" /> Undo and redo
|
### <Undo2 size="16" class="inline-block" style="margin-bottom: 2px" /><Redo2 size="16" class="inline-block" style="margin-bottom: 2px" /> 復原和重做
|
||||||
|
|
||||||
Using these buttons, you can undo or redo the last actions you performed.
|
復原或重做上一次執行的操作。
|
||||||
This applies to all actions of the interface but not to view options, application settings, or map navigation.
|
只適用於在介面上直接進行的所有操作,不適用於顯示選項、應用設定或地圖導航。
|
||||||
|
|
||||||
### <Info size="16" class="inline-block" style="margin-bottom: 2px" /> Info...
|
### <Info size="16" class="inline-block" style="margin-bottom: 2px" /> 資訊…
|
||||||
|
|
||||||
Open the information dialog of the currently selected file item, where you can see and edit its name and description.
|
用於查看或編輯所選檔案項的名稱和說明資訊。用於查看或編輯所選檔案項的名稱和說明資訊。
|
||||||
|
|
||||||
### <PaintBucket size="16" class="inline-block" style="margin-bottom: 2px" /> Appearance...
|
### <PaintBucket size="16" class="inline-block" style="margin-bottom: 2px" /> 外觀
|
||||||
|
|
||||||
Open the appearance dialog, where you can change the color, opacity, and width of the selected file items on the map.
|
用於調整所選檔案項在地圖上顯示的軌跡顏色、不透明度和闊度。
|
||||||
|
|
||||||
### <EyeOff size="16" class="inline-block" style="margin-bottom: 2px" /> Hide/unhide
|
### <EyeOff size="16" class="inline-block" style="margin-bottom: 2px" /> 隱藏/顯示
|
||||||
|
|
||||||
Toggle the visibility of the selected file items on the map.
|
切換所選檔案項在地圖上的可見性。
|
||||||
|
|
||||||
### <Plus size="16" class="inline-block" style="margin-bottom: 2px" /> New track
|
### <Plus size="16" class="inline-block" style="margin-bottom: 2px" /> 新建軌跡
|
||||||
|
|
||||||
Create a new track in the selected file.
|
在所選檔案項中建立一條新軌跡。
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
This action is only available when the tree layout of the files list is enabled.
|
此操作僅在啟用樹形佈局時可用,
|
||||||
Additionally, the selection must be a single file.
|
所選內容必須是一個檔案。
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|
||||||
### <Plus size="16" class="inline-block" style="margin-bottom: 2px" /> New segment
|
### <Plus size="16" class="inline-block" style="margin-bottom: 2px" /> 新建路段
|
||||||
|
|
||||||
Create a new segment in the selected track.
|
在所選軌跡中建立一個新路段。
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
This action is only available when the tree layout of the files list is enabled.
|
此操作僅在啟用樹形佈局時可用,
|
||||||
Additionally, the selection must be a single track.
|
且所選內容必須是單條軌跡。
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|
||||||
### <FileStack size="16" class="inline-block" style="margin-bottom: 2px" /> Select all
|
### <FileStack size="16" class="inline-block" style="margin-bottom: 2px" /> 全選
|
||||||
|
|
||||||
Add all file items in the current hierarchy level to the selection.
|
加入當前檔案層級中所有內容到選取中。
|
||||||
|
|
||||||
### <Maximize size="16" class="inline-block" style="margin-bottom: 2px" /> Center
|
### <Maximize size="16" class="inline-block" style="margin-bottom: 2px" /> 置中
|
||||||
|
|
||||||
Center the map on the selected file items.
|
根據所選檔案項調整地圖顯示中心。
|
||||||
|
|
||||||
### <ClipboardCopy size="16" class="inline-block" style="margin-bottom: 2px" /> Copy
|
### <ClipboardCopy size="16" class="inline-block" style="margin-bottom: 2px" /> 複製
|
||||||
|
|
||||||
Copy the selected file items to the clipboard.
|
複製所選檔案項到剪貼簿。
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
This action is only available when the tree layout of the files list is enabled.
|
此操作僅在啟用樹形佈局時可用,
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|
||||||
### <Scissors size="16" class="inline-block" style="margin-bottom: 2px" /> Cut
|
### <Scissors size="16" class="inline-block" style="margin-bottom: 2px" /> 剪下
|
||||||
|
|
||||||
Cut the selected file items to the clipboard.
|
剪下所選檔案項到剪貼簿。
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
This action is only available when the tree layout of the files list is enabled.
|
此操作僅在啟用樹形佈局時可用,
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|
||||||
### <ClipboardPaste size="16" class="inline-block" style="margin-bottom: 2px" /> Paste
|
### <ClipboardPaste size="16" class="inline-block" style="margin-bottom: 2px" /> 貼上
|
||||||
|
|
||||||
Paste the file items from the clipboard to the current hierarchy level if they are compatible with it.
|
如果剪貼簿中的內容與當前檔案層級相容,進行貼上操作。
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
This action is only available when the tree layout of the files list is enabled.
|
此操作僅在啟用樹形佈局時可用,
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|
||||||
### <Trash2 size="16" class="inline-block" style="margin-bottom: 2px" /> Delete
|
### <Trash2 size="16" class="inline-block" style="margin-bottom: 2px" /> 刪除
|
||||||
|
|
||||||
Delete the selected file items.
|
刪除所選檔案項。
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: File actions
|
title: 檔案
|
||||||
---
|
---
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -9,44 +9,44 @@ title: File actions
|
|||||||
|
|
||||||
# { title }
|
# { title }
|
||||||
|
|
||||||
The file actions menu contains a set of pretty self-explanatory file operations.
|
該菜單中的操作非常清晰。
|
||||||
|
|
||||||
### <Plus size="16" class="inline-block" style="margin-bottom: 2px" /> New
|
### <Plus size="16" class="inline-block" style="margin-bottom: 2px" /> 新增
|
||||||
|
|
||||||
Create a new empty file.
|
創造一個新的空白檔案。
|
||||||
|
|
||||||
### <FolderOpen size="16" class="inline-block" style="margin-bottom: 2px" /> Open...
|
### <FolderOpen size="16" class="inline-block" style="margin-bottom: 2px" /> 開啟…
|
||||||
|
|
||||||
Open files from your computer.
|
開啟本地檔案。
|
||||||
|
|
||||||
<DocsNote>
|
<DocsNote>
|
||||||
|
|
||||||
You can also drag and drop files directly from your file system into the window.
|
支援將檔案直接拖放到窗口中。
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|
||||||
### <Copy size="16" class="inline-block" style="margin-bottom: 2px" /> Duplicate
|
### <Copy size="16" class="inline-block" style="margin-bottom: 2px" /> 複製
|
||||||
|
|
||||||
Create a copy of the currently selected files.
|
創造當前選中檔案的副本。
|
||||||
|
|
||||||
### <FileX size="16" class="inline-block" style="margin-bottom: 2px" /> Delete
|
### <FileX size="16" class="inline-block" style="margin-bottom: 2px" /> 刪除
|
||||||
|
|
||||||
Delete the currently selected files.
|
刪除當前選中的檔案。
|
||||||
|
|
||||||
### <FileX size="16" class="inline-block" style="margin-bottom: 2px" /> Delete all
|
### <FileX size="16" class="inline-block" style="margin-bottom: 2px" /> 全部刪除
|
||||||
|
|
||||||
Delete all files.
|
刪除全部檔案。
|
||||||
|
|
||||||
### <Download size="16" class="inline-block" style="margin-bottom: 2px" /> Export...
|
### <Download size="16" class="inline-block" style="margin-bottom: 2px" /> 匯出...
|
||||||
|
|
||||||
Open the export dialog to save the currently selected files to your computer.
|
保存當前選取檔案到本地。
|
||||||
|
|
||||||
### <Download size="16" class="inline-block" style="margin-bottom: 2px" /> Export all...
|
### <Download size="16" class="inline-block" style="margin-bottom: 2px" /> 匯出所有…
|
||||||
|
|
||||||
Open the export dialog to save all files to your computer.
|
保存所有檔案到本地。
|
||||||
|
|
||||||
<DocsNote type="warning">
|
<DocsNote type="warning">
|
||||||
|
|
||||||
If your download does not start after clicking the download button, please check your browser settings to allow downloads from <b>gpx.studio</b>.
|
點選下載按鈕後若無反應,請檢查瀏覽器設定以允許其從 <b>gpx.studio</b> 下載。
|
||||||
|
|
||||||
</DocsNote>
|
</DocsNote>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Settings
|
title: 設定
|
||||||
---
|
---
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -9,7 +9,7 @@ title: Settings
|
|||||||
|
|
||||||
# { title }
|
# { title }
|
||||||
|
|
||||||
### <Ruler size="16" class="inline-block" style="margin-bottom: 2px" /> Distance units
|
### <Ruler size="16" class="inline-block" style="margin-bottom: 2px" /> 距離單位
|
||||||
|
|
||||||
Change the units used to display distances in the interface.
|
Change the units used to display distances in the interface.
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ title: Route planning and editing
|
|||||||
|
|
||||||
The route planning and editing tool allows you to create and edit routes by placing or moving anchor points on the map.
|
The route planning and editing tool allows you to create and edit routes by placing or moving anchor points on the map.
|
||||||
|
|
||||||
## Settings
|
## 設定
|
||||||
|
|
||||||
As shown below, the tool dialog contains a few settings to control the routing behavior.
|
As shown below, the tool dialog contains a few settings to control the routing behavior.
|
||||||
You can minimize the dialog to save space by clicking on <button><SquareArrowUpLeft size="16" class="inline-block" style="margin-bottom: 2px" /></button>.
|
You can minimize the dialog to save space by clicking on <button><SquareArrowUpLeft size="16" class="inline-block" style="margin-bottom: 2px" /></button>.
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ title: 编辑
|
|||||||
撤销或重做最后一次执行的操作。
|
撤销或重做最后一次执行的操作。
|
||||||
仅适用于在界面上直接进行的所有操作,不适用于显示选项、应用设置或地图导航。
|
仅适用于在界面上直接进行的所有操作,不适用于显示选项、应用设置或地图导航。
|
||||||
|
|
||||||
### <Info size="16" class="inline-block" style="margin-bottom: 2px" /> 信息…
|
### <Info size="16" class="inline-block" style="margin-bottom: 2px" /> 信息
|
||||||
|
|
||||||
用于查看或编辑所选文件项的名称和说明信息。
|
用于查看或编辑所选文件项的名称和说明信息。
|
||||||
|
|
||||||
### <PaintBucket size="16" class="inline-block" style="margin-bottom: 2px" /> 外观…
|
### <PaintBucket size="16" class="inline-block" style="margin-bottom: 2px" /> 外观
|
||||||
|
|
||||||
用于调整所选文件项在地图上显示的轨迹颜色、不透明度和线宽。
|
用于调整所选文件项在地图上显示的轨迹颜色、不透明度和线宽。
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
type Dictionary = {
|
type Dictionary = {
|
||||||
[key: string]: string | Dictionary;
|
[key: string]: string | Dictionary;
|
||||||
};
|
};
|
||||||
@@ -10,6 +12,7 @@ function getDateFormatter(locale: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Locale {
|
class Locale {
|
||||||
|
private _store = writable(this);
|
||||||
private _lang = $state('');
|
private _lang = $state('');
|
||||||
private _isLoadingInitial = $state(true);
|
private _isLoadingInitial = $state(true);
|
||||||
private _isLoading = $state(true);
|
private _isLoading = $state(true);
|
||||||
@@ -38,6 +41,7 @@ class Locale {
|
|||||||
}
|
}
|
||||||
import(`../locales/${this._lang}.json`).then((module) => {
|
import(`../locales/${this._lang}.json`).then((module) => {
|
||||||
this.dictionary = module.default;
|
this.dictionary = module.default;
|
||||||
|
this._store.set(this);
|
||||||
if (this._isLoadingInitial) {
|
if (this._isLoadingInitial) {
|
||||||
this._isLoadingInitial = false;
|
this._isLoadingInitial = false;
|
||||||
}
|
}
|
||||||
@@ -67,6 +71,10 @@ class Locale {
|
|||||||
public get df() {
|
public get df() {
|
||||||
return this._df;
|
return this._df;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public subscribe(run: (value: Locale) => void, invalidate?: (value?: Locale) => void) {
|
||||||
|
return this._store.subscribe(run, invalidate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const i18n = new Locale();
|
export const i18n = new Locale();
|
||||||
|
|||||||
@@ -10,5 +10,6 @@ export const languages: Record<string, string> = {
|
|||||||
nl: 'Nederlands',
|
nl: 'Nederlands',
|
||||||
'pt-BR': 'Português (Brasil)',
|
'pt-BR': 'Português (Brasil)',
|
||||||
tr: 'Türkçe',
|
tr: 'Türkçe',
|
||||||
|
uk: 'Українська',
|
||||||
zh: '简体中文',
|
zh: '简体中文',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
import { selection } from '$lib/logic/selection';
|
import { selection } from '$lib/logic/selection';
|
||||||
import maplibregl from 'maplibre-gl';
|
import { LngLatBounds } from 'maplibre-gl';
|
||||||
import { ListFileItem, ListWaypointItem } from '$lib/components/file-list/file-list';
|
import { ListFileItem, ListWaypointItem } from '$lib/components/file-list/file-list';
|
||||||
import { fileStateCollection, GPXFileStateCollectionObserver } from '$lib/logic/file-state';
|
import { fileStateCollection, GPXFileStateCollectionObserver } from '$lib/logic/file-state';
|
||||||
import { gpxStatistics } from '$lib/logic/statistics';
|
import { gpxStatistics } from '$lib/logic/statistics';
|
||||||
@@ -10,7 +10,7 @@ import type { Coordinates } from 'gpx';
|
|||||||
import { page } from '$app/state';
|
import { page } from '$app/state';
|
||||||
|
|
||||||
export class BoundsManager {
|
export class BoundsManager {
|
||||||
private _bounds: maplibregl.LngLatBounds = new maplibregl.LngLatBounds();
|
private _bounds: LngLatBounds = new LngLatBounds();
|
||||||
private _files: Set<string> = new Set();
|
private _files: Set<string> = new Set();
|
||||||
private _fileStateCollectionObserver: GPXFileStateCollectionObserver | null = null;
|
private _fileStateCollectionObserver: GPXFileStateCollectionObserver | null = null;
|
||||||
private _unsubscribes: (() => void)[] = [];
|
private _unsubscribes: (() => void)[] = [];
|
||||||
@@ -75,7 +75,7 @@ export class BoundsManager {
|
|||||||
this._unsubscribes.push(
|
this._unsubscribes.push(
|
||||||
map.subscribe((map_) => {
|
map.subscribe((map_) => {
|
||||||
if (!map_) return;
|
if (!map_) return;
|
||||||
map_.fitBounds(this._bounds, { padding: 80, linear: true, easing: () => 1 });
|
map_.fitBounds(this._bounds, { padding: 80, linear: true, animate: false });
|
||||||
this.reset();
|
this.reset();
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -87,12 +87,12 @@ export class BoundsManager {
|
|||||||
}
|
}
|
||||||
this._unsubscribes.forEach((unsubscribe) => unsubscribe());
|
this._unsubscribes.forEach((unsubscribe) => unsubscribe());
|
||||||
this._unsubscribes = [];
|
this._unsubscribes = [];
|
||||||
this._bounds = new maplibregl.LngLatBounds([180, 90, -180, -90]);
|
this._bounds = new LngLatBounds([180, 90, -180, -90]);
|
||||||
}
|
}
|
||||||
|
|
||||||
centerMapOnSelection() {
|
centerMapOnSelection() {
|
||||||
let selected = get(selection).getSelected();
|
let selected = get(selection).getSelected();
|
||||||
let bounds = new maplibregl.LngLatBounds();
|
let bounds = new LngLatBounds();
|
||||||
|
|
||||||
if (selected.find((item) => item instanceof ListWaypointItem)) {
|
if (selected.find((item) => item instanceof ListWaypointItem)) {
|
||||||
selection.applyToOrderedSelectedItemsFromFile((fileId, level, items) => {
|
selection.applyToOrderedSelectedItemsFromFile((fileId, level, items) => {
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import { ListItem, ListLevel } from '$lib/components/file-list/file-list';
|
import { ListItem, ListLevel } from '$lib/components/file-list/file-list';
|
||||||
import { GPXFile, GPXStatistics, GPXStatisticsGroup, type Track } from 'gpx';
|
import { GPXFile, GPXStatistics, GPXStatisticsGroup, type Track } from 'gpx';
|
||||||
import maplibregl from 'maplibre-gl';
|
import { LngLatBounds } from 'maplibre-gl';
|
||||||
|
|
||||||
export class GPXStatisticsTree {
|
export class GPXStatisticsTree {
|
||||||
level: ListLevel;
|
level: ListLevel;
|
||||||
statistics: {
|
statistics: {
|
||||||
[key: string]: GPXStatisticsTree | GPXStatistics;
|
[key: string]: GPXStatisticsTree | GPXStatistics;
|
||||||
} = {};
|
} = {};
|
||||||
wptBounds: maplibregl.LngLatBounds;
|
wptBounds: LngLatBounds;
|
||||||
|
|
||||||
constructor(element: GPXFile | Track) {
|
constructor(element: GPXFile | Track) {
|
||||||
this.wptBounds = new maplibregl.LngLatBounds();
|
this.wptBounds = new LngLatBounds();
|
||||||
if (element instanceof GPXFile) {
|
if (element instanceof GPXFile) {
|
||||||
this.level = ListLevel.FILE;
|
this.level = ListLevel.FILE;
|
||||||
element.children.forEach((child, index) => {
|
element.children.forEach((child, index) => {
|
||||||
@@ -49,11 +49,11 @@ export class GPXStatisticsTree {
|
|||||||
return statistics;
|
return statistics;
|
||||||
}
|
}
|
||||||
|
|
||||||
intersectsBBox(bounds: maplibregl.LngLatBounds): boolean {
|
intersectsBBox(bounds: LngLatBounds): boolean {
|
||||||
for (let key in this.statistics) {
|
for (let key in this.statistics) {
|
||||||
const stats = this.statistics[key];
|
const stats = this.statistics[key];
|
||||||
if (stats instanceof GPXStatistics) {
|
if (stats instanceof GPXStatistics) {
|
||||||
const bbox = new maplibregl.LngLatBounds(
|
const bbox = new LngLatBounds(
|
||||||
stats.global.bounds.southWest,
|
stats.global.bounds.southWest,
|
||||||
stats.global.bounds.northEast
|
stats.global.bounds.northEast
|
||||||
);
|
);
|
||||||
@@ -67,7 +67,7 @@ export class GPXStatisticsTree {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
intersectsWaypointBBox(bounds: maplibregl.LngLatBounds): boolean {
|
intersectsWaypointBBox(bounds: LngLatBounds): boolean {
|
||||||
return !this.wptBounds.isEmpty() && this.wptBounds.intersects(bounds);
|
return !this.wptBounds.isEmpty() && this.wptBounds.intersects(bounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { twMerge } from 'tailwind-merge';
|
|||||||
import { base } from '$app/paths';
|
import { base } from '$app/paths';
|
||||||
import { languages } from '$lib/languages';
|
import { languages } from '$lib/languages';
|
||||||
import { TrackPoint, Waypoint, type Coordinates, crossarcDistance, distance, GPXFile } from 'gpx';
|
import { TrackPoint, Waypoint, type Coordinates, crossarcDistance, distance, GPXFile } from 'gpx';
|
||||||
import maplibregl from 'maplibre-gl';
|
import { Map as MapLibreMap, LngLatBounds } from 'maplibre-gl';
|
||||||
import { pointToTile, pointToTileFraction } from '@mapbox/tilebelt';
|
import { pointToTile, pointToTileFraction } from '@mapbox/tilebelt';
|
||||||
import type { GPXStatisticsTree } from '$lib/logic/statistics-tree';
|
import type { GPXStatisticsTree } from '$lib/logic/statistics-tree';
|
||||||
import { ListTrackSegmentItem } from '$lib/components/file-list/file-list';
|
import { ListTrackSegmentItem } from '$lib/components/file-list/file-list';
|
||||||
@@ -58,7 +58,7 @@ export function getClosestTrackSegments(
|
|||||||
let segmentBounds = segmentStatistics.global.bounds;
|
let segmentBounds = segmentStatistics.global.bounds;
|
||||||
let northEast = segmentBounds.northEast;
|
let northEast = segmentBounds.northEast;
|
||||||
let southWest = segmentBounds.southWest;
|
let southWest = segmentBounds.southWest;
|
||||||
let bounds = new maplibregl.LngLatBounds(southWest, northEast);
|
let bounds = new LngLatBounds(southWest, northEast);
|
||||||
if (bounds.contains(point)) {
|
if (bounds.contains(point)) {
|
||||||
segmentBoundsDistances.push([0, trackIndex, segmentIndex]);
|
segmentBoundsDistances.push([0, trackIndex, segmentIndex]);
|
||||||
} else {
|
} else {
|
||||||
@@ -106,7 +106,7 @@ export function getElevation(
|
|||||||
let coordinates = points.map((point) =>
|
let coordinates = points.map((point) =>
|
||||||
point instanceof TrackPoint || point instanceof Waypoint ? point.getCoordinates() : point
|
point instanceof TrackPoint || point instanceof Waypoint ? point.getCoordinates() : point
|
||||||
);
|
);
|
||||||
let bbox = new maplibregl.LngLatBounds();
|
let bbox = new LngLatBounds();
|
||||||
coordinates.forEach((coord) => bbox.extend(coord));
|
coordinates.forEach((coord) => bbox.extend(coord));
|
||||||
|
|
||||||
let tiles = coordinates.map((coord) => pointToTile(coord.lon, coord.lat, ELEVATION_ZOOM));
|
let tiles = coordinates.map((coord) => pointToTile(coord.lon, coord.lat, ELEVATION_ZOOM));
|
||||||
@@ -193,7 +193,7 @@ export function getElevation(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function loadSVGIcon(map: maplibregl.Map, id: string, svg: string, size: number = 100) {
|
export function loadSVGIcon(map: MapLibreMap, id: string, svg: string, size: number = 100) {
|
||||||
if (!map.hasImage(id)) {
|
if (!map.hasImage(id)) {
|
||||||
let icon = new Image(size, size);
|
let icon = new Image(size, size);
|
||||||
icon.onload = () => {
|
icon.onload = () => {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
"switch_basemap": "Zur vorherigen Basemap wechseln",
|
"switch_basemap": "Zur vorherigen Basemap wechseln",
|
||||||
"toggle_overlays": "Overlay umschalten",
|
"toggle_overlays": "Overlay umschalten",
|
||||||
"toggle_3d": "3D umschalten",
|
"toggle_3d": "3D umschalten",
|
||||||
"fullscreen": "Full screen",
|
"fullscreen": "Vollbildmodus",
|
||||||
"settings": "Einstellungen",
|
"settings": "Einstellungen",
|
||||||
"distance_units": "Entfernungseinheiten",
|
"distance_units": "Entfernungseinheiten",
|
||||||
"metric": "Metrisch",
|
"metric": "Metrisch",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
},
|
},
|
||||||
"elevation": {
|
"elevation": {
|
||||||
"button": "Höhendaten anfragen",
|
"button": "Höhendaten anfragen",
|
||||||
"help": "Requesting elevation data will erase the existing elevation data, if any, and replace it with data from Mapterhorn.",
|
"help": "Das Anfordern von Höhendaten löscht die vorhandenen Höhendaten, falls vorhanden, und ersetzt diese durch Daten von Mapterhorn.",
|
||||||
"help_no_selection": "Wählen Sie ein Datei-Element, um Höhendaten anzufordern."
|
"help_no_selection": "Wählen Sie ein Datei-Element, um Höhendaten anzufordern."
|
||||||
},
|
},
|
||||||
"waypoint": {
|
"waypoint": {
|
||||||
@@ -305,7 +305,7 @@
|
|||||||
"united_kingdom": "Großbritannien",
|
"united_kingdom": "Großbritannien",
|
||||||
"united_states": "USA",
|
"united_states": "USA",
|
||||||
"libertyTopo": "Liberty Topo",
|
"libertyTopo": "Liberty Topo",
|
||||||
"libertySatellite": "Liberty Satellite",
|
"libertySatellite": "Liberty Satellit",
|
||||||
"osm": "OpenMapTiles OSM",
|
"osm": "OpenMapTiles OSM",
|
||||||
"osmTopo": "OpenMapTiles OSM Topo",
|
"osmTopo": "OpenMapTiles OSM Topo",
|
||||||
"esriSatellite": "Esri Satellite",
|
"esriSatellite": "Esri Satellite",
|
||||||
|
|||||||
+18
-18
@@ -36,7 +36,7 @@
|
|||||||
"switch_basemap": "Aldatu aurreko mapa erabiltzera",
|
"switch_basemap": "Aldatu aurreko mapa erabiltzera",
|
||||||
"toggle_overlays": "Txandakatu geruzak",
|
"toggle_overlays": "Txandakatu geruzak",
|
||||||
"toggle_3d": "Txandakatu 3D",
|
"toggle_3d": "Txandakatu 3D",
|
||||||
"fullscreen": "Full screen",
|
"fullscreen": "Pantaila osoa",
|
||||||
"settings": "Ezarpenak",
|
"settings": "Ezarpenak",
|
||||||
"distance_units": "Distantzia unitateak",
|
"distance_units": "Distantzia unitateak",
|
||||||
"metric": "Metrikoa",
|
"metric": "Metrikoa",
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
"ctrl": "Ctrl",
|
"ctrl": "Ctrl",
|
||||||
"click": "Klik",
|
"click": "Klik",
|
||||||
"drag": "Arrastatu",
|
"drag": "Arrastatu",
|
||||||
"right_click_drag": "Right-click drag",
|
"right_click_drag": "Eskuin klik eta errestan eraman",
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"button": "Informazioa...",
|
"button": "Informazioa...",
|
||||||
"name": "Izena",
|
"name": "Izena",
|
||||||
@@ -192,8 +192,8 @@
|
|||||||
"from": "Hasiera puntua errepide hurbilenetik oso hurrun dago",
|
"from": "Hasiera puntua errepide hurbilenetik oso hurrun dago",
|
||||||
"via": "Puntua errepide hurbilenetik oso hurrun dago",
|
"via": "Puntua errepide hurbilenetik oso hurrun dago",
|
||||||
"to": "Bukaera puntua errepide hurbilenetik oso hurrun dago",
|
"to": "Bukaera puntua errepide hurbilenetik oso hurrun dago",
|
||||||
"distance": "The end point is too far from the start point",
|
"distance": "Bukaera-puntua hasiera-puntutik urrutiegi dago",
|
||||||
"connection": "No connection found between the points",
|
"connection": "Ez da konexiorik topatu puntuen artean",
|
||||||
"timeout": "Ibilbidea kalkulatzea luzeegi joan da, saiatu hurbilago dauden puntuak gehitzen"
|
"timeout": "Ibilbidea kalkulatzea luzeegi joan da, saiatu hurbilago dauden puntuak gehitzen"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
},
|
},
|
||||||
"elevation": {
|
"elevation": {
|
||||||
"button": "Eskatu altueraren datuak",
|
"button": "Eskatu altueraren datuak",
|
||||||
"help": "Requesting elevation data will erase the existing elevation data, if any, and replace it with data from Mapterhorn.",
|
"help": "Kota-datuak eskatzeak lehendik dauden kota-datuak ezabatuko ditu, halakorik balego, eta Mapterhorn-eko datuekin ordezkatuko dira.",
|
||||||
"help_no_selection": "Aukeratu fitxategi bat altuera datuak eskatzeko."
|
"help_no_selection": "Aukeratu fitxategi bat altuera datuak eskatzeko."
|
||||||
},
|
},
|
||||||
"waypoint": {
|
"waypoint": {
|
||||||
@@ -277,7 +277,7 @@
|
|||||||
"new": "Geruza pertsonalizatu berria",
|
"new": "Geruza pertsonalizatu berria",
|
||||||
"edit": "Editatu geruza pertsonalizatua",
|
"edit": "Editatu geruza pertsonalizatua",
|
||||||
"urls": "URLa(k)",
|
"urls": "URLa(k)",
|
||||||
"url_placeholder": "WMTS, WMS or MapLibre style JSON",
|
"url_placeholder": "WMTS, WMS edo MapLibre estiloko JSON",
|
||||||
"max_zoom": "Zoom max",
|
"max_zoom": "Zoom max",
|
||||||
"layer_type": "Geruza mota",
|
"layer_type": "Geruza mota",
|
||||||
"basemap": "Oinarrizko-mapa",
|
"basemap": "Oinarrizko-mapa",
|
||||||
@@ -305,7 +305,7 @@
|
|||||||
"united_kingdom": "Erresuma Batua",
|
"united_kingdom": "Erresuma Batua",
|
||||||
"united_states": "Ameriketako Estatu Batuak",
|
"united_states": "Ameriketako Estatu Batuak",
|
||||||
"libertyTopo": "Liberty Topo",
|
"libertyTopo": "Liberty Topo",
|
||||||
"libertySatellite": "Liberty Satellite",
|
"libertySatellite": "Liberty Satelitea",
|
||||||
"osm": "OpenMapTiles OSM",
|
"osm": "OpenMapTiles OSM",
|
||||||
"osmTopo": "OpenMapTiles OSM Topo",
|
"osmTopo": "OpenMapTiles OSM Topo",
|
||||||
"esriSatellite": "Esri Satellite",
|
"esriSatellite": "Esri Satellite",
|
||||||
@@ -494,7 +494,7 @@
|
|||||||
"email": "Eposta",
|
"email": "Eposta",
|
||||||
"contribute": "Lagundu",
|
"contribute": "Lagundu",
|
||||||
"supported_by": "hauek lagunduta",
|
"supported_by": "hauek lagunduta",
|
||||||
"features": "Features",
|
"features": "Funtzioak",
|
||||||
"route_planning": "Bideak planifikatzea",
|
"route_planning": "Bideak planifikatzea",
|
||||||
"route_planning_description": "OpenStreetMapen datuetan oinarritutako interfaze erabilterraza kirol bakoitzerako ibilbideak sortzeko.",
|
"route_planning_description": "OpenStreetMapen datuetan oinarritutako interfaze erabilterraza kirol bakoitzerako ibilbideak sortzeko.",
|
||||||
"file_processing": "Fitxategien prozesaketa aurreratua",
|
"file_processing": "Fitxategien prozesaketa aurreratua",
|
||||||
@@ -503,15 +503,15 @@
|
|||||||
"maps_description": "Oinarrizko mapa, geruza eta interes-puntuen bilduma zabala. Zure aire-libreko ekintzak planifikatzen lagunduko dizu!",
|
"maps_description": "Oinarrizko mapa, geruza eta interes-puntuen bilduma zabala. Zure aire-libreko ekintzak planifikatzen lagunduko dizu!",
|
||||||
"data_visualization": "Datuak bistaratzea",
|
"data_visualization": "Datuak bistaratzea",
|
||||||
"data_visualization_description": "Grabatutako ekintzak edo etorkizuneko zure bideak aztertzeko altuera-profil interaktiboa.",
|
"data_visualization_description": "Grabatutako ekintzak edo etorkizuneko zure bideak aztertzeko altuera-profil interaktiboa.",
|
||||||
"philosophy": "Philosophy",
|
"philosophy": "Filosofia",
|
||||||
"foss": "Free, ad-free and open source",
|
"foss": "Doakoa, propagandarik gabe eta kode irekikoa",
|
||||||
"foss_description": "The website is free to use, without ads, and the source code is publicly available on GitHub.",
|
"foss_description": "Webgunea doakoa da, iragarkirik gabe, eta iturburu-kodea publikoki eskuragarri dago GitHub-en.",
|
||||||
"privacy": "Privacy-friendly",
|
"privacy": "Pribatutasuna zaintzen du",
|
||||||
"privacy_description": "Your GPX files never leave your browser. No tracking, no data collection.",
|
"privacy_description": "Zure GPX fitxategiak ez dira inoiz zure nabigatzailetik irteten. Ez dago jarraipenik, ez datu-bilketarik.",
|
||||||
"community": "Made possible by the community",
|
"community": "Komunitateak posible egin du",
|
||||||
"community_description": "gpx.studio has an amazing community that has covered its costs through donations for years, while shaping the project through feature suggestions, bug reports, and translations into many languages.",
|
"community_description": "gpx.studio-k komunitate harrigarri bat du, urte luzez dohaintzen bidez bere kostuak estali dituena, proiektuaren ezaugarri-iradokizunen, akatsen txostenen eta hizkuntza askotarako itzulpenen bidez moldatu dena.",
|
||||||
"support_button": "Support gpx.studio on Open Collective",
|
"support_button": "Lagundu gpx.studio Open Collectiveren bidez",
|
||||||
"translate_button": "Help translate the website on Crowdin"
|
"translate_button": "Lagundu webgunea itzultzen Crowdin-en"
|
||||||
},
|
},
|
||||||
"docs": {
|
"docs": {
|
||||||
"translate": "Lagundu itzulpenarekin Crowdinen",
|
"translate": "Lagundu itzulpenarekin Crowdinen",
|
||||||
@@ -536,7 +536,7 @@
|
|||||||
},
|
},
|
||||||
"embedding": {
|
"embedding": {
|
||||||
"title": "Sortu zure mapa",
|
"title": "Sortu zure mapa",
|
||||||
"maptiler_key": "MapTiler key (optional, only required for MapTiler maps)",
|
"maptiler_key": "MapTiler gakoa (aukeran, bakarrik behar da MapTiler mapetan)",
|
||||||
"file_urls": "Fitxategien URLak (komarekin banatuta)",
|
"file_urls": "Fitxategien URLak (komarekin banatuta)",
|
||||||
"drive_ids": "Google Drive fitxategien IDak (komarekin banatuta)",
|
"drive_ids": "Google Drive fitxategien IDak (komarekin banatuta)",
|
||||||
"basemap": "Oinarrizko-mapa",
|
"basemap": "Oinarrizko-mapa",
|
||||||
|
|||||||
+23
-23
@@ -28,15 +28,15 @@
|
|||||||
"undo": "Visszavonás ",
|
"undo": "Visszavonás ",
|
||||||
"redo": "Újra",
|
"redo": "Újra",
|
||||||
"delete": "Törlés",
|
"delete": "Törlés",
|
||||||
"delete_all": "Delete all",
|
"delete_all": "Összes törlése",
|
||||||
"select_all": "Összes kijelölése",
|
"select_all": "Összes kijelölése",
|
||||||
"view": "Nézet",
|
"view": "Nézet",
|
||||||
"elevation_profile": "Magassági profil",
|
"elevation_profile": "Magassági profil",
|
||||||
"tree_file_view": "File tree",
|
"tree_file_view": "Adat-fa nézet",
|
||||||
"switch_basemap": "Váltás az előző alaptérképre",
|
"switch_basemap": "Váltás az előző alaptérképre",
|
||||||
"toggle_overlays": "Átfedés váltása",
|
"toggle_overlays": "Átfedés váltása",
|
||||||
"toggle_3d": "3D nézet bekapcsolása",
|
"toggle_3d": "3D nézet bekapcsolása",
|
||||||
"fullscreen": "Full screen",
|
"fullscreen": "Teljes képernyő",
|
||||||
"settings": "Beállítások",
|
"settings": "Beállítások",
|
||||||
"distance_units": "Távolságmérés mértékegységei",
|
"distance_units": "Távolságmérés mértékegységei",
|
||||||
"metric": "Metrikus",
|
"metric": "Metrikus",
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
"ctrl": "Ctrl",
|
"ctrl": "Ctrl",
|
||||||
"click": "Kattints",
|
"click": "Kattints",
|
||||||
"drag": "Húzza",
|
"drag": "Húzza",
|
||||||
"right_click_drag": "Right-click drag",
|
"right_click_drag": "Jobb kattintásos mozgatás",
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"button": "Infó...",
|
"button": "Infó...",
|
||||||
"name": "Név",
|
"name": "Név",
|
||||||
@@ -82,7 +82,7 @@
|
|||||||
"center": "Középre ",
|
"center": "Középre ",
|
||||||
"open_in": "Megnyitás itt ",
|
"open_in": "Megnyitás itt ",
|
||||||
"copy_coordinates": "Koordináták másolása",
|
"copy_coordinates": "Koordináták másolása",
|
||||||
"edit_osm": "Edit in OpenStreetMap"
|
"edit_osm": "Szerkesztés OpenStreetMap-ben"
|
||||||
},
|
},
|
||||||
"toolbar": {
|
"toolbar": {
|
||||||
"routing": {
|
"routing": {
|
||||||
@@ -192,8 +192,8 @@
|
|||||||
"from": "A kiindulási pont túl messze van a legközelebbi úttól",
|
"from": "A kiindulási pont túl messze van a legközelebbi úttól",
|
||||||
"via": "A köztes pont túl messze van a legközelebbi úttól",
|
"via": "A köztes pont túl messze van a legközelebbi úttól",
|
||||||
"to": "A végpont túl messze van a legközelebbi úttól",
|
"to": "A végpont túl messze van a legközelebbi úttól",
|
||||||
"distance": "The end point is too far from the start point",
|
"distance": "A végpont túl messze van a kezdőponttól",
|
||||||
"connection": "No connection found between the points",
|
"connection": "Nem található kapcsolat a két pont között",
|
||||||
"timeout": "Az útvonal kiszámítása túl sokáig tartott. Próbáljon meg közelebbi pontokat adni egymáshoz"
|
"timeout": "Az útvonal kiszámítása túl sokáig tartott. Próbáljon meg közelebbi pontokat adni egymáshoz"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -224,18 +224,18 @@
|
|||||||
"help_merge_traces": "A kiválasztott útvonalak összekapcsolása egyetlen folyamatos útvonalat hoz létre.",
|
"help_merge_traces": "A kiválasztott útvonalak összekapcsolása egyetlen folyamatos útvonalat hoz létre.",
|
||||||
"help_cannot_merge_traces": "Kiválasztásának több útvonalat kell tartalmaznia ahhoz, hogy összekapcsolják őket.",
|
"help_cannot_merge_traces": "Kiválasztásának több útvonalat kell tartalmaznia ahhoz, hogy összekapcsolják őket.",
|
||||||
"help_merge_contents": "A kiválasztott elemek tartalmának egyesítésével az összes tartalom az első elemen belül csoportosul.",
|
"help_merge_contents": "A kiválasztott elemek tartalmának egyesítésével az összes tartalom az első elemen belül csoportosul.",
|
||||||
"help_cannot_merge_contents": "Your selection must contain several items to merge their contents.",
|
"help_cannot_merge_contents": "A kijelölésnek több tételt kell tartalmaznia, ahhoz hogy egybevonható legyen.",
|
||||||
"selection_tip": "Tip: use {KEYBOARD_SHORTCUT} to add items to the selection."
|
"selection_tip": "Tipp: használd a {KEYBOARD_SHORTCUT}, hogy hozzá adj a kijelöléshez."
|
||||||
},
|
},
|
||||||
"extract": {
|
"extract": {
|
||||||
"tooltip": "Extract contents to separate items",
|
"tooltip": "Tartalom szétrobbantása különálló elemekké",
|
||||||
"button": "Extract",
|
"button": "Szétrobbant",
|
||||||
"help": "Extracting the contents of the selected items will create a separate item for each of their contents.",
|
"help": "A kijelölt tartalmak szétrobbantása különálló elemeket hoz létre minden egyes elemből.",
|
||||||
"help_invalid_selection": "Több nyomvonalat kell tartalmazzon a kijelölés a kinyeréshez."
|
"help_invalid_selection": "Több nyomvonalat kell tartalmazzon a kijelölés a kinyeréshez."
|
||||||
},
|
},
|
||||||
"elevation": {
|
"elevation": {
|
||||||
"button": "Magassági információk lekérése",
|
"button": "Magassági információk lekérése",
|
||||||
"help": "Requesting elevation data will erase the existing elevation data, if any, and replace it with data from Mapterhorn.",
|
"help": "A \"Magassági adatok lekérése\" törölni fogja a meglévő magassági adatokat és lecseréli a Mapterhorn által szolgáltatott adatokra.",
|
||||||
"help_no_selection": "Select a file item to request elevation data."
|
"help_no_selection": "Select a file item to request elevation data."
|
||||||
},
|
},
|
||||||
"waypoint": {
|
"waypoint": {
|
||||||
@@ -286,7 +286,7 @@
|
|||||||
"update": "Réteg feltöltése"
|
"update": "Réteg feltöltése"
|
||||||
},
|
},
|
||||||
"opacity": "Átfedés átlátszósága",
|
"opacity": "Átfedés átlátszósága",
|
||||||
"terrain": "Terrain source",
|
"terrain": "Domborzat forrása",
|
||||||
"label": {
|
"label": {
|
||||||
"basemaps": "Alaptérkép",
|
"basemaps": "Alaptérkép",
|
||||||
"overlays": "Térkép rétegek",
|
"overlays": "Térkép rétegek",
|
||||||
@@ -305,7 +305,7 @@
|
|||||||
"united_kingdom": "Anglia",
|
"united_kingdom": "Anglia",
|
||||||
"united_states": "Amerika",
|
"united_states": "Amerika",
|
||||||
"libertyTopo": "Liberty Topo",
|
"libertyTopo": "Liberty Topo",
|
||||||
"libertySatellite": "Liberty Satellite",
|
"libertySatellite": "Liberty Műhold",
|
||||||
"osm": "OpenMapTiles OSM",
|
"osm": "OpenMapTiles OSM",
|
||||||
"osmTopo": "OpenMapTiles OSM Topo",
|
"osmTopo": "OpenMapTiles OSM Topo",
|
||||||
"esriSatellite": "Esri Satellite",
|
"esriSatellite": "Esri Satellite",
|
||||||
@@ -325,7 +325,7 @@
|
|||||||
"ignFrScan25": "IGN SCAN25",
|
"ignFrScan25": "IGN SCAN25",
|
||||||
"ignFrSatellite": "IGN Műhold",
|
"ignFrSatellite": "IGN Műhold",
|
||||||
"ignEs": "IGN Topo",
|
"ignEs": "IGN Topo",
|
||||||
"ignEsSatellite": "IGN Satellite",
|
"ignEsSatellite": "IGN Műhold",
|
||||||
"ordnanceSurvey": "Hadifelmérés",
|
"ordnanceSurvey": "Hadifelmérés",
|
||||||
"norwayTopo": "Norvégia topográfiai térképe 4",
|
"norwayTopo": "Norvégia topográfiai térképe 4",
|
||||||
"finlandTopo": "Lantmäteriverket Tereptérkép",
|
"finlandTopo": "Lantmäteriverket Tereptérkép",
|
||||||
@@ -333,7 +333,7 @@
|
|||||||
"usgs": "USGS",
|
"usgs": "USGS",
|
||||||
"bikerouterGravel": "kerékpár és terepkerékpár út",
|
"bikerouterGravel": "kerékpár és terepkerékpár út",
|
||||||
"cyclOSMlite": "CyclOSM Lite",
|
"cyclOSMlite": "CyclOSM Lite",
|
||||||
"mapterhornHillshade": "Mapterhorn Hillshade",
|
"mapterhornHillshade": "Mapterhorn Árnyékolt Domborzat",
|
||||||
"openRailwayMap": "OpenRailwayMap",
|
"openRailwayMap": "OpenRailwayMap",
|
||||||
"swisstopoSlope": "swisstopo Lejtő",
|
"swisstopoSlope": "swisstopo Lejtő",
|
||||||
"swisstopoHiking": "swisstopo Túra",
|
"swisstopoHiking": "swisstopo Túra",
|
||||||
@@ -363,7 +363,7 @@
|
|||||||
"water": "Víz",
|
"water": "Víz",
|
||||||
"shower": "Zuhanyozó",
|
"shower": "Zuhanyozó",
|
||||||
"shelter": "Menedék",
|
"shelter": "Menedék",
|
||||||
"cemetery": "Cemetery",
|
"cemetery": "Temető / Sírkert",
|
||||||
"motorized": "Autók és Motorok",
|
"motorized": "Autók és Motorok",
|
||||||
"fuel-station": "Benzinkút",
|
"fuel-station": "Benzinkút",
|
||||||
"parking": "Parkoló",
|
"parking": "Parkoló",
|
||||||
@@ -374,11 +374,11 @@
|
|||||||
"viewpoint": "Kilátó",
|
"viewpoint": "Kilátó",
|
||||||
"hotel": "Hotel",
|
"hotel": "Hotel",
|
||||||
"campsite": "Kemping",
|
"campsite": "Kemping",
|
||||||
"hut": "Hut",
|
"hut": "Kunyhó",
|
||||||
"picnic": "Piknikező hely",
|
"picnic": "Piknikező hely",
|
||||||
"summit": "Csúcs",
|
"summit": "Csúcs",
|
||||||
"pass": "Pass",
|
"pass": "Hágó",
|
||||||
"climbing": "Climbing",
|
"climbing": "Mászás",
|
||||||
"bicycle": "Kerékpár",
|
"bicycle": "Kerékpár",
|
||||||
"bicycle-parking": "Kerékpár parkoló",
|
"bicycle-parking": "Kerékpár parkoló",
|
||||||
"bicycle-rental": "Kerékpár bérélés",
|
"bicycle-rental": "Kerékpár bérélés",
|
||||||
@@ -401,12 +401,12 @@
|
|||||||
"temperature": "Hőmérséklet",
|
"temperature": "Hőmérséklet",
|
||||||
"speed": "Sebesség",
|
"speed": "Sebesség",
|
||||||
"pace": "Tempó",
|
"pace": "Tempó",
|
||||||
"heartrate": "Heart rate",
|
"heartrate": "Pulzusszám",
|
||||||
"cadence": "Lépés/Pedál ütem",
|
"cadence": "Lépés/Pedál ütem",
|
||||||
"power": "Erő",
|
"power": "Erő",
|
||||||
"slope": "Erőkifejtési szintkép színekkel",
|
"slope": "Erőkifejtési szintkép színekkel",
|
||||||
"surface": "Szintkép",
|
"surface": "Szintkép",
|
||||||
"highway": "Category",
|
"highway": "Kategória",
|
||||||
"time": "Idő",
|
"time": "Idő",
|
||||||
"moving": "Moving",
|
"moving": "Moving",
|
||||||
"total": "Összes",
|
"total": "Összes",
|
||||||
|
|||||||
+24
-24
@@ -13,7 +13,7 @@
|
|||||||
"new_track": "Новий трек",
|
"new_track": "Новий трек",
|
||||||
"new_segment": "Новий сегмент",
|
"new_segment": "Новий сегмент",
|
||||||
"open": "Відкрити...",
|
"open": "Відкрити...",
|
||||||
"duplicate": "Дублікат",
|
"duplicate": "Дублювати",
|
||||||
"copy": "Копіювати",
|
"copy": "Копіювати",
|
||||||
"paste": "Вставити",
|
"paste": "Вставити",
|
||||||
"cut": "Вирізати",
|
"cut": "Вирізати",
|
||||||
@@ -33,10 +33,10 @@
|
|||||||
"view": "Вигляд",
|
"view": "Вигляд",
|
||||||
"elevation_profile": "Профіль рельєфу",
|
"elevation_profile": "Профіль рельєфу",
|
||||||
"tree_file_view": "Дерево файлів",
|
"tree_file_view": "Дерево файлів",
|
||||||
"switch_basemap": "Перехід до попередньої базової карти",
|
"switch_basemap": "Попередня базова карта",
|
||||||
"toggle_overlays": "Перемикання накладок",
|
"toggle_overlays": "Перемкнути накладені шари",
|
||||||
"toggle_3d": "Перемикнути 3D",
|
"toggle_3d": "Перемикнути 3D",
|
||||||
"fullscreen": "Full screen",
|
"fullscreen": "На весь екран",
|
||||||
"settings": "Налаштування",
|
"settings": "Налаштування",
|
||||||
"distance_units": "Одиниці виміру відстані",
|
"distance_units": "Одиниці виміру відстані",
|
||||||
"metric": "Метричні",
|
"metric": "Метричні",
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
"more": "Більше...",
|
"more": "Більше...",
|
||||||
"donate": "Пожертвувати",
|
"donate": "Пожертвувати",
|
||||||
"ctrl": "Ctrl",
|
"ctrl": "Ctrl",
|
||||||
"click": "Клац",
|
"click": "Клік мишею",
|
||||||
"drag": "Перетягти",
|
"drag": "Перетягти",
|
||||||
"right_click_drag": "Перетягування правою кнопкою миші",
|
"right_click_drag": "Перетягування правою кнопкою миші",
|
||||||
"metadata": {
|
"metadata": {
|
||||||
@@ -74,12 +74,12 @@
|
|||||||
"style": {
|
"style": {
|
||||||
"button": "Зовнішність...",
|
"button": "Зовнішність...",
|
||||||
"color": "Колір",
|
"color": "Колір",
|
||||||
"opacity": "Непрозорість",
|
"opacity": "Прозорість",
|
||||||
"width": "Ширина"
|
"width": "Ширина"
|
||||||
},
|
},
|
||||||
"hide": "Приховати",
|
"hide": "Приховати",
|
||||||
"unhide": "Показати",
|
"unhide": "Показати",
|
||||||
"center": "Центр",
|
"center": "По центру",
|
||||||
"open_in": "Відкрити в",
|
"open_in": "Відкрити в",
|
||||||
"copy_coordinates": "Копіювати координати",
|
"copy_coordinates": "Копіювати координати",
|
||||||
"edit_osm": "Редагувати в OpenStreetMap"
|
"edit_osm": "Редагувати в OpenStreetMap"
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
"use_routing_tooltip": "З'єднати опорні точки через мережу доріг або по прямій лінії, якщо вони недоступні",
|
"use_routing_tooltip": "З'єднати опорні точки через мережу доріг або по прямій лінії, якщо вони недоступні",
|
||||||
"allow_private": "Дозволити приватні дороги",
|
"allow_private": "Дозволити приватні дороги",
|
||||||
"reverse": {
|
"reverse": {
|
||||||
"button": "У зворотньому порядку",
|
"button": "У зворотньому напрямку",
|
||||||
"tooltip": "Змінити напрямок маршруту"
|
"tooltip": "Змінити напрямок маршруту"
|
||||||
},
|
},
|
||||||
"route_back_to_start": {
|
"route_back_to_start": {
|
||||||
@@ -200,29 +200,29 @@
|
|||||||
"scissors": {
|
"scissors": {
|
||||||
"tooltip": "Обрізати або розділити",
|
"tooltip": "Обрізати або розділити",
|
||||||
"crop": "Обрізати",
|
"crop": "Обрізати",
|
||||||
"split_as": "Розділити слід на",
|
"split_as": "Розділити трек на",
|
||||||
"help_invalid_selection": "Виберіть слід для обрізання чи розділення.",
|
"help_invalid_selection": "Виберіть трек для обрізання або розділення.",
|
||||||
"help": "Використовуйте повзунок, щоб обрізати слід, або розділіть його, клацнувши на один з маркерів розбиття або на самому маршруті."
|
"help": "Використовуйте повзунок, щоб обрізати слід, або розділіть його, клацнувши на один з маркерів розбиття або на самому маршруті."
|
||||||
},
|
},
|
||||||
"time": {
|
"time": {
|
||||||
"tooltip": "Керування даними часу",
|
"tooltip": "Керувати даними часу",
|
||||||
"start": "Початок",
|
"start": "Початок",
|
||||||
"end": "Кінець",
|
"end": "Кінець",
|
||||||
"total_time": "Час руху",
|
"total_time": "Час руху",
|
||||||
"pick_date": "Оберіть дату",
|
"pick_date": "Оберіть дату",
|
||||||
"artificial": "Створюйте реалістичні дані часу",
|
"artificial": "Створити реалістичні дані часу",
|
||||||
"update": "Оновити дані часу",
|
"update": "Оновити дані часу",
|
||||||
"help": "Скористайтеся формою, щоб встановити нові дані часу.",
|
"help": "Скористайтеся формою, щоб встановити нові дані часу.",
|
||||||
"help_invalid_selection": "Виберіть один трек для керування його часовими даними."
|
"help_invalid_selection": "Виберіть один трек для керування його часовими даними."
|
||||||
},
|
},
|
||||||
"merge": {
|
"merge": {
|
||||||
"merge_traces": "З'єднайте треки",
|
"merge_traces": "З'єднати треки",
|
||||||
"merge_contents": "Об'єднати вміст та зберегти треки від'єднаними",
|
"merge_contents": "Об'єднати вміст та зберегти треки від'єднаними",
|
||||||
"merge_selection": "Об'єднати вибрані",
|
"merge_selection": "Об'єднати вибрані",
|
||||||
"remove_gaps": "Видалити проміжки часу між слідами",
|
"remove_gaps": "Видалити проміжки часу між слідами",
|
||||||
"tooltip": "Об'єднати елементи",
|
"tooltip": "Об'єднати елементи",
|
||||||
"help_merge_traces": "Об'єднання вибраних слідів створить один безперервний слід.",
|
"help_merge_traces": "Об'єднання вибраних слідів створить один безперервний слід.",
|
||||||
"help_cannot_merge_traces": "Ваш вибір повинен містити декілька слідів для їх об'єднання.",
|
"help_cannot_merge_traces": "Щоб з’єднати треки, вибір має містити кілька треків.",
|
||||||
"help_merge_contents": "Об'єднання вмісту вибраних елементів згрупує все у першому елементі.",
|
"help_merge_contents": "Об'єднання вмісту вибраних елементів згрупує все у першому елементі.",
|
||||||
"help_cannot_merge_contents": "Ваш вибір має містити декілька елементів для об'єднання їх вмісту.",
|
"help_cannot_merge_contents": "Ваш вибір має містити декілька елементів для об'єднання їх вмісту.",
|
||||||
"selection_tip": "Порада: використовуйте {KEYBOARD_SHORTCUT}, щоб додати елементи до виділення."
|
"selection_tip": "Порада: використовуйте {KEYBOARD_SHORTCUT}, щоб додати елементи до виділення."
|
||||||
@@ -235,11 +235,11 @@
|
|||||||
},
|
},
|
||||||
"elevation": {
|
"elevation": {
|
||||||
"button": "Запит даних висот",
|
"button": "Запит даних висот",
|
||||||
"help": "Requesting elevation data will erase the existing elevation data, if any, and replace it with data from Mapterhorn.",
|
"help": "Запит даних висот призведе до видалення наявних даних висот, якщо вони є, і замінить їх даними з Mapterhorn.",
|
||||||
"help_no_selection": "Виберіть елемент файлу, щоб запросити дані про висоту."
|
"help_no_selection": "Виберіть елемент файлу, щоб запросити дані про висоту."
|
||||||
},
|
},
|
||||||
"waypoint": {
|
"waypoint": {
|
||||||
"tooltip": "Створення та редагування визначних місць",
|
"tooltip": "Створити та редагувати точки інтересу",
|
||||||
"icon": "Іконка",
|
"icon": "Іконка",
|
||||||
"link": "Посилання",
|
"link": "Посилання",
|
||||||
"longitude": "Довгота",
|
"longitude": "Довгота",
|
||||||
@@ -255,17 +255,17 @@
|
|||||||
"number_of_points": "Кількість точок GPS",
|
"number_of_points": "Кількість точок GPS",
|
||||||
"button": "Мінімізувати",
|
"button": "Мінімізувати",
|
||||||
"help": "Використовуйте повзунок, щоб вибрати кількість точок GPS, які потрібно зберегти.",
|
"help": "Використовуйте повзунок, щоб вибрати кількість точок GPS, які потрібно зберегти.",
|
||||||
"help_no_selection": "Оберіть слід для зменшення кількості його GPS точок."
|
"help_no_selection": "Виберіть трек, щоб зменшити кількість його GPS-точок."
|
||||||
},
|
},
|
||||||
"clean": {
|
"clean": {
|
||||||
"tooltip": "Очистити GPS точки та точки інтересів, використовуючи прямокутний вибір",
|
"tooltip": "Очистити GPS точки та точки інтересів, використовуючи прямокутний вибір",
|
||||||
"delete_trackpoints": "Видалити точки GPS",
|
"delete_trackpoints": "Видалити точки GPS",
|
||||||
"delete_waypoints": "Видалити цікаві місця",
|
"delete_waypoints": "Видалити цікаві місця",
|
||||||
"delete_inside": "Видалити всередині виділення",
|
"delete_inside": "Видалити всередині виділення",
|
||||||
"delete_outside": "Видалити зовнішній вибір",
|
"delete_outside": "Видалити за межами виділення",
|
||||||
"button": "Видалити",
|
"button": "Видалити",
|
||||||
"help": "Виберіть прямокутну область на карті, щоб видалити точки GPS та точки інтересу.",
|
"help": "Виберіть прямокутну область на карті, щоб видалити точки GPS та точки інтересу.",
|
||||||
"help_no_selection": "Виберіть слід, щоб очистити точки GPS та точки інтересу."
|
"help_no_selection": "Виберіть трек для очищення GPS-точок і точок інтересу."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"layers": {
|
"layers": {
|
||||||
@@ -281,15 +281,15 @@
|
|||||||
"max_zoom": "Максимальний зум",
|
"max_zoom": "Максимальний зум",
|
||||||
"layer_type": "Тип шару",
|
"layer_type": "Тип шару",
|
||||||
"basemap": "Базова карта",
|
"basemap": "Базова карта",
|
||||||
"overlay": "Накладання",
|
"overlay": "Накладений шар",
|
||||||
"create": "Створити шар",
|
"create": "Створити шар",
|
||||||
"update": "Оновити шар"
|
"update": "Оновити шар"
|
||||||
},
|
},
|
||||||
"opacity": "Непрозорість накладання",
|
"opacity": "Прозорість накладеного шару",
|
||||||
"terrain": "Джерело інформації про місцевість",
|
"terrain": "Джерело інформації про місцевість",
|
||||||
"label": {
|
"label": {
|
||||||
"basemaps": "Базові карти",
|
"basemaps": "Базові карти",
|
||||||
"overlays": "Накладання",
|
"overlays": "Накладені шари",
|
||||||
"custom": "Користувацька",
|
"custom": "Користувацька",
|
||||||
"world": "Світ",
|
"world": "Світ",
|
||||||
"countries": "Країни",
|
"countries": "Країни",
|
||||||
@@ -396,7 +396,7 @@
|
|||||||
},
|
},
|
||||||
"quantities": {
|
"quantities": {
|
||||||
"distance": "Відстань",
|
"distance": "Відстань",
|
||||||
"elevation": "Підвищення",
|
"elevation": "Висота",
|
||||||
"elevation_gain_loss": "Набір і втрата висоти",
|
"elevation_gain_loss": "Набір і втрата висоти",
|
||||||
"temperature": "Температура",
|
"temperature": "Температура",
|
||||||
"speed": "Швидкість",
|
"speed": "Швидкість",
|
||||||
@@ -404,7 +404,7 @@
|
|||||||
"heartrate": "Пульс",
|
"heartrate": "Пульс",
|
||||||
"cadence": "Каденс",
|
"cadence": "Каденс",
|
||||||
"power": "Потужність",
|
"power": "Потужність",
|
||||||
"slope": "Схил",
|
"slope": "Ухил",
|
||||||
"surface": "Поверхня",
|
"surface": "Поверхня",
|
||||||
"highway": "Категорія",
|
"highway": "Категорія",
|
||||||
"time": "Час",
|
"time": "Час",
|
||||||
|
|||||||
+433
-433
@@ -2,308 +2,308 @@
|
|||||||
"metadata": {
|
"metadata": {
|
||||||
"home_title": "線上 GPX 檔案編輯器",
|
"home_title": "線上 GPX 檔案編輯器",
|
||||||
"app_title": "app",
|
"app_title": "app",
|
||||||
"embed_title": "",
|
"embed_title": "線上 GPX 檔案編輯器",
|
||||||
"help_title": "",
|
"help_title": "幫助",
|
||||||
"404_title": "page not found",
|
"404_title": "無法找到相關頁面",
|
||||||
"description": "。"
|
"description": "線上查看、編輯和建立 GPX 檔案,包含高級路線規劃、檔案管理器、精美的地圖和詳細的資料可視化功能。"
|
||||||
},
|
},
|
||||||
"menu": {
|
"menu": {
|
||||||
"new": "New",
|
"new": "新建",
|
||||||
"new_file": "New file",
|
"new_file": "新增檔案",
|
||||||
"new_track": "New track",
|
"new_track": "新增路徑",
|
||||||
"new_segment": "New segment",
|
"new_segment": "新增路段",
|
||||||
"open": "Open...",
|
"open": "開啟...",
|
||||||
"duplicate": "Duplicate",
|
"duplicate": "建立副本",
|
||||||
"copy": "Copy",
|
"copy": "複製",
|
||||||
"paste": "Paste",
|
"paste": "貼上",
|
||||||
"cut": "剪下",
|
"cut": "剪下",
|
||||||
"export": "匯出……",
|
"export": "匯出……",
|
||||||
"export_all": "匯出所有……",
|
"export_all": "匯出所有……",
|
||||||
"export_options": "Export options",
|
"export_options": "匯出選項",
|
||||||
"support_message": "The tool is free to use, but not free to run. Please consider supporting the website if you use it frequently. Thank you!",
|
"support_message": "本工具免費使用,但運行此網站有成本。若您經常使用,請考慮捐贈以支持我們。非常感謝!",
|
||||||
"support_button": "Help keep the website free",
|
"support_button": "幫助網站保持免費",
|
||||||
"download_file": "Download file",
|
"download_file": "下載檔案",
|
||||||
"download_files": "Download files",
|
"download_files": "下載所有檔案",
|
||||||
"edit": "Edit",
|
"edit": "編輯",
|
||||||
"undo": "Undo",
|
"undo": "復原",
|
||||||
"redo": "Redo",
|
"redo": "重做",
|
||||||
"delete": "Delete",
|
"delete": "刪除",
|
||||||
"delete_all": "Delete all",
|
"delete_all": "全部刪除",
|
||||||
"select_all": "Select all",
|
"select_all": "全選",
|
||||||
"view": "View",
|
"view": "顯示",
|
||||||
"elevation_profile": "Elevation profile",
|
"elevation_profile": "海拔剖面圖",
|
||||||
"tree_file_view": "File tree",
|
"tree_file_view": "檔案樹狀圖",
|
||||||
"switch_basemap": "Switch to previous basemap",
|
"switch_basemap": "切換到上一個底圖",
|
||||||
"toggle_overlays": "Toggle overlays",
|
"toggle_overlays": "切換疊加層",
|
||||||
"toggle_3d": "Toggle 3D",
|
"toggle_3d": "切換三維檢視",
|
||||||
"fullscreen": "Full screen",
|
"fullscreen": "全螢幕",
|
||||||
"settings": "Settings",
|
"settings": "設定",
|
||||||
"distance_units": "Distance units",
|
"distance_units": "距離單位",
|
||||||
"metric": "Metric",
|
"metric": "公制",
|
||||||
"imperial": "Imperial",
|
"imperial": "英制",
|
||||||
"nautical": "Nautical",
|
"nautical": "航海",
|
||||||
"velocity_units": "Velocity units",
|
"velocity_units": "速度單位",
|
||||||
"temperature_units": "Temperature units",
|
"temperature_units": "溫度單位",
|
||||||
"celsius": "Celsius",
|
"celsius": "攝氏",
|
||||||
"fahrenheit": "Fahrenheit",
|
"fahrenheit": "華氏",
|
||||||
"language": "Language",
|
"language": "語言",
|
||||||
"mode": "Theme",
|
"mode": "主題",
|
||||||
"system": "System",
|
"system": "系統",
|
||||||
"light": "Light",
|
"light": "淺色",
|
||||||
"dark": "Dark",
|
"dark": "深色",
|
||||||
"street_view_source": "街景原始檔",
|
"street_view_source": "街景原始檔",
|
||||||
"mapillary": "Mapillary",
|
"mapillary": "Mapillary",
|
||||||
"google": "Google",
|
"google": "Google",
|
||||||
"toggle_street_view": "Street view",
|
"toggle_street_view": "街景",
|
||||||
"layers": "Map layers...",
|
"layers": "地圖圖層...",
|
||||||
"distance_markers": "Distance markers",
|
"distance_markers": "距離標記",
|
||||||
"direction_markers": "Direction arrows",
|
"direction_markers": "方向箭頭",
|
||||||
"help": "Help",
|
"help": "幫助",
|
||||||
"more": "More...",
|
"more": "更多...",
|
||||||
"donate": "Donate",
|
"donate": "捐贈",
|
||||||
"ctrl": "Ctrl",
|
"ctrl": "Ctrl",
|
||||||
"click": "Click",
|
"click": "點選",
|
||||||
"drag": "Drag",
|
"drag": "拖動",
|
||||||
"right_click_drag": "Right-click drag",
|
"right_click_drag": "右鍵拖動",
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"button": "Info...",
|
"button": "資訊...",
|
||||||
"name": "Name",
|
"name": "名稱",
|
||||||
"description": "Description",
|
"description": "說明",
|
||||||
"save": "Save"
|
"save": "保存"
|
||||||
},
|
},
|
||||||
"style": {
|
"style": {
|
||||||
"button": "Appearance...",
|
"button": "外觀...",
|
||||||
"color": "Color",
|
"color": "配色",
|
||||||
"opacity": "Opacity",
|
"opacity": "透明度",
|
||||||
"width": "Width"
|
"width": "闊度"
|
||||||
},
|
},
|
||||||
"hide": "Hide",
|
"hide": "隱藏",
|
||||||
"unhide": "Unhide",
|
"unhide": "取消隱藏",
|
||||||
"center": "Center",
|
"center": "置中",
|
||||||
"open_in": "Open in",
|
"open_in": "打開於",
|
||||||
"copy_coordinates": "Copy coordinates",
|
"copy_coordinates": "複製座標",
|
||||||
"edit_osm": "Edit in OpenStreetMap"
|
"edit_osm": "在 OpenStreetMap 中編輯"
|
||||||
},
|
},
|
||||||
"toolbar": {
|
"toolbar": {
|
||||||
"routing": {
|
"routing": {
|
||||||
"tooltip": "Plan or edit a route",
|
"tooltip": "規劃或編輯路線",
|
||||||
"activity": "Activity",
|
"activity": "活動",
|
||||||
"use_routing": "Routing",
|
"use_routing": "路線",
|
||||||
"use_routing_tooltip": "Connect anchor points via road network, or in a straight line if disabled",
|
"use_routing_tooltip": "通過路網連接錨點,若停用用直線連接",
|
||||||
"allow_private": "Allow private roads",
|
"allow_private": "允許私家路",
|
||||||
"reverse": {
|
"reverse": {
|
||||||
"button": "Reverse",
|
"button": "反向",
|
||||||
"tooltip": "Reverse the direction of the route"
|
"tooltip": "反轉路線方向"
|
||||||
},
|
},
|
||||||
"route_back_to_start": {
|
"route_back_to_start": {
|
||||||
"button": "Back to start",
|
"button": "返回起點",
|
||||||
"tooltip": "Connect the last point of the route with the starting point"
|
"tooltip": "連接路線的起點與終點"
|
||||||
},
|
},
|
||||||
"round_trip": {
|
"round_trip": {
|
||||||
"button": "Round trip",
|
"button": "往返路線",
|
||||||
"tooltip": "Return to the starting point by the same route"
|
"tooltip": "按原路返回起點"
|
||||||
},
|
},
|
||||||
"start_loop_here": "Start loop here",
|
"start_loop_here": "在此開始循環",
|
||||||
"help_no_file": "Select a trace to use the routing tool, or click on the map to start creating a new route.",
|
"help_no_file": "選擇軌跡進行編輯,或在地圖上點選以建立新路線。",
|
||||||
"help": "Click on the map to add a new anchor point, or drag existing ones to change the route.",
|
"help": "點選地圖以加入新錨點,或拖動現有錨點以改變路線。",
|
||||||
"activities": {
|
"activities": {
|
||||||
"bike": "Bike",
|
"bike": "單車",
|
||||||
"racing_bike": "Road bike",
|
"racing_bike": "公路單車",
|
||||||
"gravel_bike": "Gravel bike",
|
"gravel_bike": "礫石單車",
|
||||||
"mountain_bike": "Mountain bike",
|
"mountain_bike": "越野單車",
|
||||||
"foot": "Run/hike",
|
"foot": "跑步/遠足",
|
||||||
"motorcycle": "Motorcycle",
|
"motorcycle": "電單車",
|
||||||
"water": "Water",
|
"water": "水上活動",
|
||||||
"railway": "Railway"
|
"railway": "鐵路"
|
||||||
},
|
},
|
||||||
"surface": {
|
"surface": {
|
||||||
"unknown": "Unknown",
|
"unknown": "未知",
|
||||||
"paved": "Paved",
|
"paved": "鋪砌路面",
|
||||||
"unpaved": "Unpaved",
|
"unpaved": "未鋪砌路面",
|
||||||
"asphalt": "Asphalt",
|
"asphalt": "瀝青路",
|
||||||
"concrete": "Concrete",
|
"concrete": "混凝土",
|
||||||
"cobblestone": "Cobblestone",
|
"cobblestone": "鵝卵石",
|
||||||
"paving_stones": "鋪路石",
|
"paving_stones": "鋪路石",
|
||||||
"sett": "石板",
|
"sett": "石板",
|
||||||
"metal": "Metal",
|
"metal": "金屬",
|
||||||
"wood": "Wood",
|
"wood": "木材",
|
||||||
"compacted": "Compacted gravel",
|
"compacted": "壓實的礫石",
|
||||||
"fine_gravel": "Fine gravel",
|
"fine_gravel": "細礫",
|
||||||
"gravel": "Gravel",
|
"gravel": "砂礫",
|
||||||
"pebblestone": "Pebblestone",
|
"pebblestone": "卵石",
|
||||||
"rock": "Rock",
|
"rock": "岩石",
|
||||||
"dirt": "Dirt",
|
"dirt": "泥土",
|
||||||
"ground": "Ground",
|
"ground": "地面",
|
||||||
"earth": "Earth",
|
"earth": "土地",
|
||||||
"mud": "Mud",
|
"mud": "泥地",
|
||||||
"sand": "Sand",
|
"sand": "沙粒",
|
||||||
"grass": "Grass",
|
"grass": "草地",
|
||||||
"grass_paver": "Grass paver",
|
"grass_paver": "草坪",
|
||||||
"clay": "Clay",
|
"clay": "黏土",
|
||||||
"stone": "Stone"
|
"stone": "石頭"
|
||||||
},
|
},
|
||||||
"highway": {
|
"highway": {
|
||||||
"unknown": "Unknown",
|
"unknown": "未知類型",
|
||||||
"motorway": "Highway",
|
"motorway": "高速公路",
|
||||||
"motorway_link": "Highway link",
|
"motorway_link": "高速公路引道",
|
||||||
"trunk": "Primary road",
|
"trunk": "快速公路",
|
||||||
"trunk_link": "Primary road link",
|
"trunk_link": "快速公路連接路",
|
||||||
"primary": "Primary road",
|
"primary": "快速公路",
|
||||||
"primary_link": "Primary road link",
|
"primary_link": "快速公路連接路",
|
||||||
"secondary": "Secondary road",
|
"secondary": "主要道路",
|
||||||
"secondary_link": "Secondary road link",
|
"secondary_link": "主要道路連接路",
|
||||||
"tertiary": "Tertiary road",
|
"tertiary": "支路",
|
||||||
"tertiary_link": "Tertiary road link",
|
"tertiary_link": "支路連接路",
|
||||||
"unclassified": "Minor road",
|
"unclassified": "小路",
|
||||||
"residential": "Residential road",
|
"residential": "居住區道路",
|
||||||
"living_street": "Living street",
|
"living_street": "住宅街道",
|
||||||
"service": "Service road",
|
"service": "輔助道路",
|
||||||
"track": "Track",
|
"track": "小徑(未鋪設道路)",
|
||||||
"footway": "Footway",
|
"footway": "徑",
|
||||||
"path": "Path",
|
"path": "小徑",
|
||||||
"pedestrian": "Pedestrian",
|
"pedestrian": "行人路",
|
||||||
"cycleway": "Cycleway",
|
"cycleway": "單車徑",
|
||||||
"steps": "Steps",
|
"steps": "石級",
|
||||||
"road": "Road",
|
"road": "道路",
|
||||||
"bridleway": "Horseriding path",
|
"bridleway": "馬道",
|
||||||
"platform": "Platform",
|
"platform": "停靠站台",
|
||||||
"raceway": "競賽賽道",
|
"raceway": "競賽賽道",
|
||||||
"rest_area": "Rest area",
|
"rest_area": "停車區",
|
||||||
"abandoned": "Abandoned",
|
"abandoned": "廢棄道路",
|
||||||
"services": "Services",
|
"services": "服務區",
|
||||||
"corridor": "Corridor",
|
"corridor": "走廊",
|
||||||
"bus_stop": "Bus stop",
|
"bus_stop": "巴士站",
|
||||||
"busway": "Busway",
|
"busway": "巴士線",
|
||||||
"elevator": "Elevator",
|
"elevator": "升降機",
|
||||||
"via_ferrata": "Via ferrata",
|
"via_ferrata": "鐵鎖攀岩",
|
||||||
"proposed": "已規劃但未興建的道路",
|
"proposed": "未興建的道路",
|
||||||
"construction": "Road under construction"
|
"construction": "興建中的道路"
|
||||||
},
|
},
|
||||||
"sac_scale": {
|
"sac_scale": {
|
||||||
"hiking": "遠足",
|
"hiking": "遠足",
|
||||||
"mountain_hiking": "登山遠足",
|
"mountain_hiking": "登山遠足",
|
||||||
"demanding_mountain_hiking": "Demanding mountain hiking",
|
"demanding_mountain_hiking": "高難度登山路徑 (T3級)",
|
||||||
"alpine_hiking": "高山遠足",
|
"alpine_hiking": "高山遠足",
|
||||||
"demanding_alpine_hiking": "Demanding alpine hiking",
|
"demanding_alpine_hiking": "高難度登山路徑 (T5級)",
|
||||||
"difficult_alpine_hiking": "Difficult alpine hiking"
|
"difficult_alpine_hiking": "高難度登山路徑 (T6級)"
|
||||||
},
|
},
|
||||||
"mtb_scale": "MTB scale",
|
"mtb_scale": "越野單車徑難度分級",
|
||||||
"error": {
|
"error": {
|
||||||
"from": "The start point is too far from the nearest road",
|
"from": "起點離最近的道路太遠",
|
||||||
"via": "The via point is too far from the nearest road",
|
"via": "途徑點離最近的道路太遠",
|
||||||
"to": "The end point is too far from the nearest road",
|
"to": "終點離最近的道路太遠",
|
||||||
"distance": "The end point is too far from the start point",
|
"distance": "起點到終點的距離太遠",
|
||||||
"connection": "No connection found between the points",
|
"connection": "找不到連接途徑點的路線",
|
||||||
"timeout": "Route calculation took too long, try adding points closer together"
|
"timeout": "軌跡計算耗時太長,請嘗試減少點與點的距離"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scissors": {
|
"scissors": {
|
||||||
"tooltip": "Crop or split",
|
"tooltip": "裁剪或拆分",
|
||||||
"crop": "Crop",
|
"crop": "裁剪",
|
||||||
"split_as": "Split the trace into",
|
"split_as": "將軌跡拆分為",
|
||||||
"help_invalid_selection": "Select a trace to crop or split.",
|
"help_invalid_selection": "須先選擇要裁剪或拆分的軌跡。",
|
||||||
"help": "Use the slider to crop the trace, or split it by clicking on one of the split markers or on the trace itself."
|
"help": "移動滑塊以確認裁剪範圍,或點選軌跡上的分割標記以拆分。"
|
||||||
},
|
},
|
||||||
"time": {
|
"time": {
|
||||||
"tooltip": "Manage time data",
|
"tooltip": "管理時間資料",
|
||||||
"start": "Start",
|
"start": "開始",
|
||||||
"end": "End",
|
"end": "結束",
|
||||||
"total_time": "Moving time",
|
"total_time": "移動時間",
|
||||||
"pick_date": "Pick a date",
|
"pick_date": "選擇日期",
|
||||||
"artificial": "Create realistic time data",
|
"artificial": "建立實際時間資料",
|
||||||
"update": "Update time data",
|
"update": "更新時間資料",
|
||||||
"help": "Use the form to set new time data.",
|
"help": "使用表單設定新的時間資料。",
|
||||||
"help_invalid_selection": "Select a single trace to manage its time data."
|
"help_invalid_selection": "選擇一個軌跡來管理時間資料。"
|
||||||
},
|
},
|
||||||
"merge": {
|
"merge": {
|
||||||
"merge_traces": "Connect the traces",
|
"merge_traces": "合併為一條連續軌跡",
|
||||||
"merge_contents": "Merge the contents and keep the traces disconnected",
|
"merge_contents": "合併但保持軌跡獨立",
|
||||||
"merge_selection": "Merge selection",
|
"merge_selection": "合併",
|
||||||
"remove_gaps": "Remove time gaps between traces",
|
"remove_gaps": "刪除軌跡的時間間隔",
|
||||||
"tooltip": "Merge items together",
|
"tooltip": "合併項目",
|
||||||
"help_merge_traces": "Connecting the selected traces will create a single continuous trace.",
|
"help_merge_traces": "連接所選內容並建立一個連續的軌跡。",
|
||||||
"help_cannot_merge_traces": "Your selection must contain several traces to connect them.",
|
"help_cannot_merge_traces": "須先選擇多個檔案以合併。",
|
||||||
"help_merge_contents": "Merging the contents of the selected items will group all the contents inside the first item.",
|
"help_merge_contents": "合併所選內容並將結果儲存於第一個檔案。",
|
||||||
"help_cannot_merge_contents": "Your selection must contain several items to merge their contents.",
|
"help_cannot_merge_contents": "須先選擇多個檔案以合併。",
|
||||||
"selection_tip": "Tip: use {KEYBOARD_SHORTCUT} to add items to the selection."
|
"selection_tip": "可使用 {KEYBOARD_SHORTCUT} 新增項目至選擇中。"
|
||||||
},
|
},
|
||||||
"extract": {
|
"extract": {
|
||||||
"tooltip": "Extract contents to separate items",
|
"tooltip": "提取為多個獨立項目",
|
||||||
"button": "Extract",
|
"button": "提取",
|
||||||
"help": "Extracting the contents of the selected items will create a separate item for each of their contents.",
|
"help": "該操作將為每個軌跡建立一個單獨的檔案。",
|
||||||
"help_invalid_selection": "Your selection must contain items with multiple traces to extract them."
|
"help_invalid_selection": "須先選擇包含多個軌跡的檔案以提取。"
|
||||||
},
|
},
|
||||||
"elevation": {
|
"elevation": {
|
||||||
"button": "Request elevation data",
|
"button": "請求海拔資料",
|
||||||
"help": "Requesting elevation data will erase the existing elevation data, if any, and replace it with data from Mapterhorn.",
|
"help": "請求成功後將移除原有的海拔資料,並使用 Mapterhorn 的海拔資料替換原有資料。",
|
||||||
"help_no_selection": "Select a file item to request elevation data."
|
"help_no_selection": "選擇要請求海拔資料的檔案。"
|
||||||
},
|
},
|
||||||
"waypoint": {
|
"waypoint": {
|
||||||
"tooltip": "Create and edit points of interest",
|
"tooltip": "建立或編輯興趣點",
|
||||||
"icon": "Icon",
|
"icon": "圖示",
|
||||||
"link": "Link",
|
"link": "連結",
|
||||||
"longitude": "Longitude",
|
"longitude": "經度",
|
||||||
"latitude": "Latitude",
|
"latitude": "緯度",
|
||||||
"create": "Create point of interest",
|
"create": "新增興趣點",
|
||||||
"add": "Add point of interest to file",
|
"add": "將興趣點加入到檔案",
|
||||||
"help": "Fill in the form to create a new point of interest, or click on an existing one to edit it. Click on the map to fill the coordinates, or drag points of interest to move them.",
|
"help": "通過表單建立新興趣點,或點選現有興趣點以編輯。 點選地圖並填充坐標點,或拖動興趣點以移動坐標。",
|
||||||
"help_no_selection": "Select a file to create or edit points of interest."
|
"help_no_selection": "選擇檔案以建立或編輯興趣點。"
|
||||||
},
|
},
|
||||||
"reduce": {
|
"reduce": {
|
||||||
"tooltip": "Reduce the number of GPS points",
|
"tooltip": "精簡 GPS 點數量",
|
||||||
"tolerance": "Tolerance",
|
"tolerance": "最大間距",
|
||||||
"number_of_points": "Number of GPS points",
|
"number_of_points": "GPS 點數量",
|
||||||
"button": "簡化",
|
"button": "簡化",
|
||||||
"help": "Use the slider to choose the number of GPS points to keep.",
|
"help": "移動滑塊以調整要保留的 GPS 點數量。",
|
||||||
"help_no_selection": "Select a trace to reduce the number of its GPS points."
|
"help_no_selection": "選擇一個軌跡以減少其 GPS 點的數量。"
|
||||||
},
|
},
|
||||||
"clean": {
|
"clean": {
|
||||||
"tooltip": "Clean GPS points and points of interest with a rectangle selection",
|
"tooltip": "使用矩形選區清除項目",
|
||||||
"delete_trackpoints": "Delete GPS points",
|
"delete_trackpoints": "刪除 GPS 點",
|
||||||
"delete_waypoints": "Delete points of interest",
|
"delete_waypoints": "刪除興趣點",
|
||||||
"delete_inside": "Delete inside selection",
|
"delete_inside": "清除選區內部項目",
|
||||||
"delete_outside": "Delete outside selection",
|
"delete_outside": "清除選區外的項目",
|
||||||
"button": "Delete",
|
"button": "刪除",
|
||||||
"help": "Select a rectangle area on the map to remove GPS points and points of interest.",
|
"help": "在地圖上繪製矩形選區以清除。",
|
||||||
"help_no_selection": "Select a trace to clean GPS points and points of interest."
|
"help_no_selection": "選擇一個軌跡以清除其 GPS 點和興趣點。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"layers": {
|
"layers": {
|
||||||
"settings": "Layer settings",
|
"settings": "圖層設定",
|
||||||
"settings_help": "Select the map layers you want to show in the interface, add custom ones, and adjust their settings.",
|
"settings_help": "選擇要在介面中顯示的地圖圖層,或加入自訂圖層,並作出必要調整。",
|
||||||
"selection": "Layer selection",
|
"selection": "選擇圖層",
|
||||||
"custom_layers": {
|
"custom_layers": {
|
||||||
"title": "Custom layers",
|
"title": "自訂圖層",
|
||||||
"new": "New custom layer",
|
"new": "新建自訂圖層",
|
||||||
"edit": "Edit custom layer",
|
"edit": "編輯自訂圖層",
|
||||||
"urls": "URL(s)",
|
"urls": "URL",
|
||||||
"url_placeholder": "WMTS, WMS or MapLibre style JSON",
|
"url_placeholder": "WMTS、WMS 或 MapLibre style JSON",
|
||||||
"max_zoom": "Max zoom",
|
"max_zoom": "最大縮放等級",
|
||||||
"layer_type": "Layer type",
|
"layer_type": "圖層類型",
|
||||||
"basemap": "Basemap",
|
"basemap": "底圖",
|
||||||
"overlay": "Overlay",
|
"overlay": "疊加層",
|
||||||
"create": "Create layer",
|
"create": "新增圖層",
|
||||||
"update": "Update layer"
|
"update": "更新圖層"
|
||||||
},
|
},
|
||||||
"opacity": "Overlay opacity",
|
"opacity": "圖層透明度",
|
||||||
"terrain": "Terrain source",
|
"terrain": "地形來源",
|
||||||
"label": {
|
"label": {
|
||||||
"basemaps": "Basemaps",
|
"basemaps": "底圖",
|
||||||
"overlays": "Overlays",
|
"overlays": "疊加層",
|
||||||
"custom": "Custom",
|
"custom": "自訂",
|
||||||
"world": "World",
|
"world": "世界",
|
||||||
"countries": "Countries",
|
"countries": "國家/地區",
|
||||||
"belgium": "Belgium",
|
"belgium": "比利時",
|
||||||
"bulgaria": "Bulgaria",
|
"bulgaria": "保加利亞",
|
||||||
"finland": "Finland",
|
"finland": "芬蘭",
|
||||||
"france": "France",
|
"france": "法國",
|
||||||
"new_zealand": "New Zealand",
|
"new_zealand": "紐西蘭",
|
||||||
"norway": "Norway",
|
"norway": "挪威",
|
||||||
"spain": "Spain",
|
"spain": "西班牙",
|
||||||
"sweden": "Sweden",
|
"sweden": "瑞典",
|
||||||
"switzerland": "Switzerland",
|
"switzerland": "瑞士",
|
||||||
"united_kingdom": "United Kingdom",
|
"united_kingdom": "英國",
|
||||||
"united_states": "United States",
|
"united_states": "美國",
|
||||||
"libertyTopo": "Liberty Topo",
|
"libertyTopo": "Liberty Topo",
|
||||||
"libertySatellite": "Liberty Satellite",
|
"libertySatellite": "Liberty Satellite",
|
||||||
"osm": "OpenMapTiles OSM",
|
"osm": "OpenMapTiles OSM",
|
||||||
@@ -316,108 +316,108 @@
|
|||||||
"utagawaVTT": "UtagawaMTB",
|
"utagawaVTT": "UtagawaMTB",
|
||||||
"linz": "LINZ Topo",
|
"linz": "LINZ Topo",
|
||||||
"linzTopo": "LINZ Topo50",
|
"linzTopo": "LINZ Topo50",
|
||||||
"swisstopoRaster": "swisstopo Raster",
|
"swisstopoRaster": "swisstopo 柵格",
|
||||||
"swisstopoVector": "swisstopo Vector",
|
"swisstopoVector": "swisstopo 向量",
|
||||||
"swisstopoSatellite": "swisstopo Satellite",
|
"swisstopoSatellite": "swisstopo 衛星地圖",
|
||||||
"ignBe": "IGN Topo",
|
"ignBe": "IGN Topo",
|
||||||
"ignFrPlan": "IGN Plan",
|
"ignFrPlan": "IGN Plan",
|
||||||
"ignFrTopo": "IGN Topo",
|
"ignFrTopo": "IGN Topo",
|
||||||
"ignFrScan25": "IGN SCAN25",
|
"ignFrScan25": "IGN SCAN25",
|
||||||
"ignFrSatellite": "IGN Satellite",
|
"ignFrSatellite": "IGN 衛星地圖",
|
||||||
"ignEs": "IGN Topo",
|
"ignEs": "IGN Topo",
|
||||||
"ignEsSatellite": "IGN Satellite",
|
"ignEsSatellite": "IGN Satellite",
|
||||||
"ordnanceSurvey": "Ordnance Survey",
|
"ordnanceSurvey": "Ordnance Survey(英國地形測量局)",
|
||||||
"norwayTopo": "Topografisk Norgeskart 4",
|
"norwayTopo": "Topografisk Norgeskart 4",
|
||||||
"finlandTopo": "Lantmäteriverket Terrängkarta",
|
"finlandTopo": "Lantmäteriverket Terrängkarta",
|
||||||
"bgMountains": "BGMountains",
|
"bgMountains": "BGMountains",
|
||||||
"usgs": "USGS",
|
"usgs": "USGS",
|
||||||
"bikerouterGravel": "bikerouter.de Gravel",
|
"bikerouterGravel": "bikerouter.de Gravel",
|
||||||
"cyclOSMlite": "CyclOSM Lite",
|
"cyclOSMlite": "CyclOSM Lite",
|
||||||
"mapterhornHillshade": "Mapterhorn Hillshade",
|
"mapterhornHillshade": "Mapterhorn Hillshade",
|
||||||
"openRailwayMap": "OpenRailwayMap",
|
"openRailwayMap": "OpenRailwayMap",
|
||||||
"swisstopoSlope": "swisstopo Slope",
|
"swisstopoSlope": "swisstopo 地形",
|
||||||
"swisstopoHiking": "swisstopo Hiking",
|
"swisstopoHiking": "swisstopo 遠足",
|
||||||
"swisstopoHikingClosures": "swisstopo Hiking Closures",
|
"swisstopoHikingClosures": "swisstopo 登山封閉路線",
|
||||||
"swisstopoCycling": "swisstopo Cycling",
|
"swisstopoCycling": "swisstopo 單車",
|
||||||
"swisstopoCyclingClosures": "swisstopo Cycling Closures",
|
"swisstopoCyclingClosures": "swisstopo 單車封閉路線",
|
||||||
"swisstopoMountainBike": "swisstopo MTB",
|
"swisstopoMountainBike": "swisstopo 越野單車",
|
||||||
"swisstopoMountainBikeClosures": "swisstopo MTB Closures",
|
"swisstopoMountainBikeClosures": "swisstopo 越野單車封閉路線",
|
||||||
"swisstopoSkiTouring": "swisstopo Ski Touring",
|
"swisstopoSkiTouring": "swisstopo 滑雪巡遊",
|
||||||
"ignFrCadastre": "IGN Cadastre",
|
"ignFrCadastre": "IGN Cadastre",
|
||||||
"ignSlope": "IGN Slope",
|
"ignSlope": "IGN 地形",
|
||||||
"ignSkiTouring": "IGN Ski Touring",
|
"ignSkiTouring": "IGN 滑雪巡遊",
|
||||||
"waymarked_trails": "Waymarked Trails",
|
"waymarked_trails": "標記路線",
|
||||||
"waymarkedTrailsHiking": "Hiking",
|
"waymarkedTrailsHiking": "遠足",
|
||||||
"waymarkedTrailsCycling": "Cycling",
|
"waymarkedTrailsCycling": "單車",
|
||||||
"waymarkedTrailsMTB": "MTB",
|
"waymarkedTrailsMTB": "越野單車",
|
||||||
"waymarkedTrailsSkating": "Skating",
|
"waymarkedTrailsSkating": "滑冰",
|
||||||
"waymarkedTrailsHorseRiding": "Horse Riding",
|
"waymarkedTrailsHorseRiding": "騎馬",
|
||||||
"waymarkedTrailsWinter": "Winter",
|
"waymarkedTrailsWinter": "冬季路線",
|
||||||
"points_of_interest": "Points of interest",
|
"points_of_interest": "興趣點",
|
||||||
"food": "Food",
|
"food": "食物",
|
||||||
"bakery": "Bakery",
|
"bakery": "麵包店",
|
||||||
"food-store": "Food Store",
|
"food-store": "食品店",
|
||||||
"eat-and-drink": "Eat and Drink",
|
"eat-and-drink": "餐飲店",
|
||||||
"amenities": "Amenities",
|
"amenities": "便利設施",
|
||||||
"toilets": "Toilets",
|
"toilets": "廁所",
|
||||||
"water": "Water",
|
"water": "飲用水",
|
||||||
"shower": "Shower",
|
"shower": "淋浴",
|
||||||
"shelter": "Shelter",
|
"shelter": "庇護所",
|
||||||
"cemetery": "Cemetery",
|
"cemetery": "墓地",
|
||||||
"motorized": "Cars and Motorcycles",
|
"motorized": "汽車和電單車",
|
||||||
"fuel-station": "Fuel Station",
|
"fuel-station": "油站",
|
||||||
"parking": "Parking",
|
"parking": "停車場",
|
||||||
"garage": "Garage",
|
"garage": "車庫",
|
||||||
"barrier": "Barrier",
|
"barrier": "障礙物",
|
||||||
"tourism": "Tourism",
|
"tourism": "旅游",
|
||||||
"attraction": "Attraction",
|
"attraction": "景點",
|
||||||
"viewpoint": "Viewpoint",
|
"viewpoint": "觀景台",
|
||||||
"hotel": "Hotel",
|
"hotel": "酒店",
|
||||||
"campsite": "Campsite",
|
"campsite": "營地",
|
||||||
"hut": "Hut",
|
"hut": "小屋",
|
||||||
"picnic": "Picnic Area",
|
"picnic": "野餐區",
|
||||||
"summit": "Summit",
|
"summit": "頂峰",
|
||||||
"pass": "Pass",
|
"pass": "山坳",
|
||||||
"climbing": "Climbing",
|
"climbing": "攀爬",
|
||||||
"bicycle": "Bicycle",
|
"bicycle": "單車",
|
||||||
"bicycle-parking": "Bicycle Parking",
|
"bicycle-parking": "單車架",
|
||||||
"bicycle-rental": "Bicycle Rental",
|
"bicycle-rental": "單車出租店",
|
||||||
"bicycle-shop": "Bicycle Shop",
|
"bicycle-shop": "單車店",
|
||||||
"public-transport": "Public Transport",
|
"public-transport": "公共交通",
|
||||||
"railway-station": "Railway Station",
|
"railway-station": "火車站",
|
||||||
"tram-stop": "Tram Stop",
|
"tram-stop": "電車站",
|
||||||
"bus-stop": "Bus Stop",
|
"bus-stop": "巴士站",
|
||||||
"ferry": "Ferry",
|
"ferry": "渡口",
|
||||||
"mapterhorn": "Mapterhorn"
|
"mapterhorn": "Mapterhorn"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"chart": {
|
"chart": {
|
||||||
"settings": "Elevation profile settings"
|
"settings": "海拔剖面圖設定"
|
||||||
},
|
},
|
||||||
"quantities": {
|
"quantities": {
|
||||||
"distance": "Distance",
|
"distance": "距離",
|
||||||
"elevation": "Elevation",
|
"elevation": "海拔",
|
||||||
"elevation_gain_loss": "Elevation gain and loss",
|
"elevation_gain_loss": "累計爬升和下降",
|
||||||
"temperature": "Temperature",
|
"temperature": "温度",
|
||||||
"speed": "Speed",
|
"speed": "速度",
|
||||||
"pace": "Pace",
|
"pace": "配速",
|
||||||
"heartrate": "Heart rate",
|
"heartrate": "心率",
|
||||||
"cadence": "Cadence",
|
"cadence": "踏頻",
|
||||||
"power": "Power",
|
"power": "功率",
|
||||||
"slope": "Slope",
|
"slope": "坡度",
|
||||||
"surface": "Surface",
|
"surface": "路面",
|
||||||
"highway": "Category",
|
"highway": "類型",
|
||||||
"time": "Time",
|
"time": "時間",
|
||||||
"moving": "Moving",
|
"moving": "運動",
|
||||||
"total": "Total",
|
"total": "全部",
|
||||||
"osm_extensions": "OpenStreetMap data"
|
"osm_extensions": "OpenStreetMap 資料"
|
||||||
},
|
},
|
||||||
"units": {
|
"units": {
|
||||||
"meters": "m",
|
"meters": "米",
|
||||||
"feet": "ft",
|
"feet": "英呎",
|
||||||
"kilometers": "km",
|
"kilometers": "公里",
|
||||||
"miles": "mi",
|
"miles": "英里",
|
||||||
"nautical_miles": "nm",
|
"nautical_miles": "海里",
|
||||||
"celsius": "°C",
|
"celsius": "°C",
|
||||||
"fahrenheit": "°F",
|
"fahrenheit": "°F",
|
||||||
"kilometers_per_hour": "km/h",
|
"kilometers_per_hour": "km/h",
|
||||||
@@ -425,136 +425,136 @@
|
|||||||
"minutes_per_kilometer": "min/km",
|
"minutes_per_kilometer": "min/km",
|
||||||
"minutes_per_mile": "min/mi",
|
"minutes_per_mile": "min/mi",
|
||||||
"minutes_per_nautical_mile": "min/nm",
|
"minutes_per_nautical_mile": "min/nm",
|
||||||
"knots": "kn",
|
"knots": "節",
|
||||||
"heartrate": "bpm",
|
"heartrate": "bpm",
|
||||||
"cadence": "rpm",
|
"cadence": "rpm",
|
||||||
"power": "W"
|
"power": "W"
|
||||||
},
|
},
|
||||||
"gpx": {
|
"gpx": {
|
||||||
"file": "File",
|
"file": "檔案",
|
||||||
"files": "Files",
|
"files": "檔案",
|
||||||
"track": "Track",
|
"track": "軌跡",
|
||||||
"tracks": "Tracks",
|
"tracks": "軌跡",
|
||||||
"segment": "Segment",
|
"segment": "路段",
|
||||||
"segments": "Segments",
|
"segments": "路段",
|
||||||
"waypoint": "Point of interest",
|
"waypoint": "興趣點",
|
||||||
"waypoints": "Points of interest",
|
"waypoints": "興趣點",
|
||||||
"symbol": {
|
"symbol": {
|
||||||
"alert": "Alert",
|
"alert": "警告",
|
||||||
"anchor": "Anchor",
|
"anchor": "錨點",
|
||||||
"bank": "Bank",
|
"bank": "銀行",
|
||||||
"beach": "Beach",
|
"beach": "海灘",
|
||||||
"bike_trail": "Bike Trail",
|
"bike_trail": "單車徑",
|
||||||
"binoculars": "Binoculars",
|
"binoculars": "望遠鏡",
|
||||||
"bridge": "Bridge",
|
"bridge": "橋",
|
||||||
"building": "Building",
|
"building": "大廈",
|
||||||
"campground": "Campsite",
|
"campground": "營地",
|
||||||
"car": "Car",
|
"car": "車輛",
|
||||||
"car_repair": "Garage",
|
"car_repair": "車庫",
|
||||||
"convenience_store": "Convenience Store",
|
"convenience_store": "便利店",
|
||||||
"crossing": "Crossing",
|
"crossing": "交叉路口",
|
||||||
"department_store": "Department Store",
|
"department_store": "百貨店",
|
||||||
"drinking_water": "Water",
|
"drinking_water": "飲用水",
|
||||||
"exit": "Exit",
|
"exit": "出口",
|
||||||
"lodge": "Hut",
|
"lodge": "小屋",
|
||||||
"lodging": "Accommodation",
|
"lodging": "住宿",
|
||||||
"forest": "Forest",
|
"forest": "森林",
|
||||||
"gas_station": "Fuel Station",
|
"gas_station": "油站",
|
||||||
"ground_transportation": "Ground Transportation",
|
"ground_transportation": "地面交通",
|
||||||
"hotel": "Hotel",
|
"hotel": "酒店",
|
||||||
"house": "House",
|
"house": "住宅",
|
||||||
"information": "Information",
|
"information": "資訊",
|
||||||
"park": "Park",
|
"park": "公園",
|
||||||
"parking_area": "Parking",
|
"parking_area": "停車場",
|
||||||
"pharmacy": "Pharmacy",
|
"pharmacy": "藥房",
|
||||||
"picnic_area": "Picnic Area",
|
"picnic_area": "野餐區",
|
||||||
"restaurant": "Restaurant",
|
"restaurant": "餐廳",
|
||||||
"restricted_area": "Restricted Area",
|
"restricted_area": "管制區域",
|
||||||
"restroom": "Toilets",
|
"restroom": "廁所",
|
||||||
"road": "Road",
|
"road": "道路",
|
||||||
"scenic_area": "Scenic Area",
|
"scenic_area": "景區",
|
||||||
"shelter": "Shelter",
|
"shelter": "庇護所",
|
||||||
"shopping_center": "Shopping Center",
|
"shopping_center": "購物中心",
|
||||||
"shower": "Shower",
|
"shower": "淋浴",
|
||||||
"summit": "Summit",
|
"summit": "山峰",
|
||||||
"telephone": "Telephone",
|
"telephone": "電話",
|
||||||
"tunnel": "Tunnel",
|
"tunnel": "隧道",
|
||||||
"water_source": "Water Source"
|
"water_source": "水源"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"homepage": {
|
"homepage": {
|
||||||
"website": "Website",
|
"website": "官方網站",
|
||||||
"home": "Home",
|
"home": "首頁",
|
||||||
"app": "App",
|
"app": "應用程式",
|
||||||
"contact": "Contact",
|
"contact": "聯絡我們",
|
||||||
"reddit": "Reddit",
|
"reddit": "Reddit",
|
||||||
"facebook": "Facebook",
|
"facebook": "Facebook",
|
||||||
"github": "GitHub",
|
"github": "GitHub",
|
||||||
"crowdin": "Crowdin",
|
"crowdin": "Crowdin",
|
||||||
"email": "Email",
|
"email": "電郵",
|
||||||
"contribute": "Contribute",
|
"contribute": "參與貢獻",
|
||||||
"supported_by": "supported by",
|
"supported_by": "技術支援",
|
||||||
"features": "Features",
|
"features": "功能",
|
||||||
"route_planning": "Route planning",
|
"route_planning": "路線規劃",
|
||||||
"route_planning_description": "An intuitive interface to create itineraries tailored to each sport, based on OpenStreetMap data.",
|
"route_planning_description": "基於 OpenStreetMap 數據,在直觀的介面中為每項運動建立量身定製的行程。",
|
||||||
"file_processing": "Advanced file processing",
|
"file_processing": "高級檔案處理",
|
||||||
"file_processing_description": "A suite of tools for performing all common file processing tasks, and which can be applied to multiple files at once.",
|
"file_processing_description": "一系列常見的檔案處理工具,支援對多個檔案同時進行操作。",
|
||||||
"maps": "Global and local maps",
|
"maps": "全球和本地地圖",
|
||||||
"maps_description": "A large collection of basemaps, overlays and points of interest to help you craft your next outdoor adventure, or visualize your latest achievement.",
|
"maps_description": "內建大量地圖底圖、疊加圖層和興趣點,用於幫助規劃戶外冒險或可視化成果。",
|
||||||
"data_visualization": "Data visualization",
|
"data_visualization": "數據可視化",
|
||||||
"data_visualization_description": "An interactive elevation profile with detailed statistics to analyze recorded activities and future objectives.",
|
"data_visualization_description": "可互動的海拔剖面圖,帶有詳細的統計數據,用於分析已記錄的活動和規劃中的目標。",
|
||||||
"philosophy": "Philosophy",
|
"philosophy": "宗旨",
|
||||||
"foss": "Free, ad-free and open source",
|
"foss": "免費、無廣告、開源",
|
||||||
"foss_description": "The website is free to use, without ads, and the source code is publicly available on GitHub.",
|
"foss_description": "此網站可自由使用,無廣告,原始碼可在 GitHub 上公開查閱。",
|
||||||
"privacy": "Privacy-friendly",
|
"privacy": "注重隱私",
|
||||||
"privacy_description": "Your GPX files never leave your browser. No tracking, no data collection.",
|
"privacy_description": "你的 GPX 檔案永遠不會離開你的瀏覽器。我們不會跟蹤使用者的使用行為,也不會收集使用者產生的資料。",
|
||||||
"community": "Made possible by the community",
|
"community": "由社區驅動",
|
||||||
"community_description": "gpx.studio has an amazing community that has covered its costs through donations for years, while shaping the project through feature suggestions, bug reports, and translations into many languages.",
|
"community_description": "gpx.studio 有一個絕讚的社區,它通過社區成員的捐助持續營運。它通過社區的力量,不斷增加新的功能、修復 bug,並支援多種語言。",
|
||||||
"support_button": "Support gpx.studio on Open Collective",
|
"support_button": "在 Open Collective 上支持 gpx.studio",
|
||||||
"translate_button": "Help translate the website on Crowdin"
|
"translate_button": "在 Crowdin 上協助翻譯"
|
||||||
},
|
},
|
||||||
"docs": {
|
"docs": {
|
||||||
"translate": "Improve the translation on Crowdin",
|
"translate": "在 Crowdin 上改進此翻譯",
|
||||||
"answer_not_found": "Did not find what you were looking for?",
|
"answer_not_found": "找不到您想要的內容?",
|
||||||
"ask_on_reddit": "Ask the community on Reddit",
|
"ask_on_reddit": "在 Reddit 上詢問社區",
|
||||||
"search": {
|
"search": {
|
||||||
"search": "Search",
|
"search": "搜尋",
|
||||||
"clear": "Clear",
|
"clear": "清除",
|
||||||
"cancel": "Cancel",
|
"cancel": "取消",
|
||||||
"recent": "Recent searches",
|
"recent": "最近搜尋",
|
||||||
"no_recent": "No recent searches",
|
"no_recent": "沒有近期的搜尋紀錄",
|
||||||
"save": "Save this search",
|
"save": "保存至搜尋歷史",
|
||||||
"remove": "Remove this search from history",
|
"remove": "從搜尋歷史中移除",
|
||||||
"favorites": "Favorites",
|
"favorites": "我的最愛",
|
||||||
"remove_favorite": "Remove this search from favorites",
|
"remove_favorite": "取消收藏",
|
||||||
"to_select": "to select",
|
"to_select": "選擇",
|
||||||
"to_navigate": "to navigate",
|
"to_navigate": "切換",
|
||||||
"to_close": "to close",
|
"to_close": "退出",
|
||||||
"no_results": "No results for",
|
"no_results": "沒有找到相關資料:",
|
||||||
"no_results_suggestion": "Try searching for"
|
"no_results_suggestion": "請嘗試以下關鍵詞:"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"embedding": {
|
"embedding": {
|
||||||
"title": "Create your own map",
|
"title": "建立您的地圖",
|
||||||
"maptiler_key": "MapTiler key (optional, only required for MapTiler maps)",
|
"maptiler_key": "MapTiler key (可選,僅在使用 MapTiler 地圖時需要提供)",
|
||||||
"file_urls": "File URLs (separated by commas)",
|
"file_urls": "檔案連結(英文逗號分隔)",
|
||||||
"drive_ids": "Google Drive file IDs (separated by commas)",
|
"drive_ids": "Google 雲端硬碟檔案 IDs(英文逗號分隔)",
|
||||||
"basemap": "Basemap",
|
"basemap": "底圖",
|
||||||
"height": "Height",
|
"height": "高度",
|
||||||
"fill_by": "Fill by",
|
"fill_by": "填充方式",
|
||||||
"none": "None",
|
"none": "無填充",
|
||||||
"show_controls": "Show controls",
|
"show_controls": "顯示控制項",
|
||||||
"manual_camera": "Manual camera",
|
"manual_camera": "手動調整視角",
|
||||||
"manual_camera_description": "You can move the map below to adjust the camera position.",
|
"manual_camera_description": "移動下方地圖以調整相機位置。",
|
||||||
"latitude": "Latitude",
|
"latitude": "緯度",
|
||||||
"longitude": "Longitude",
|
"longitude": "經度",
|
||||||
"zoom": "Zoom",
|
"zoom": "縮放",
|
||||||
"pitch": "Pitch",
|
"pitch": "傾角",
|
||||||
"bearing": "Bearing",
|
"bearing": "方位",
|
||||||
"preview": "Preview",
|
"preview": "預覽",
|
||||||
"code": "Integration code"
|
"code": "整合代碼"
|
||||||
},
|
},
|
||||||
"webgl2_required": "WebGL 2 is required to display the map.",
|
"webgl2_required": "須先啟用 WebGL 2 才能顯示地圖。",
|
||||||
"enable_webgl2": "Learn how to enable WebGL 2 in your browser",
|
"enable_webgl2": "學習如何在瀏覽器中啟用 WebGL 2",
|
||||||
"page_not_found": "page not found"
|
"page_not_found": "無法找到相關頁面"
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-14
@@ -156,7 +156,7 @@
|
|||||||
"tertiary_link": "乡道/支路的连接路段",
|
"tertiary_link": "乡道/支路的连接路段",
|
||||||
"unclassified": "小型道路",
|
"unclassified": "小型道路",
|
||||||
"residential": "居住区道路",
|
"residential": "居住区道路",
|
||||||
"living_street": "生活性街道",
|
"living_street": "住宅街道",
|
||||||
"service": "服务性道路",
|
"service": "服务性道路",
|
||||||
"track": "小径(未铺设道路)",
|
"track": "小径(未铺设道路)",
|
||||||
"footway": "步行道路",
|
"footway": "步行道路",
|
||||||
@@ -187,7 +187,7 @@
|
|||||||
"demanding_alpine_hiking": "相对简单的攀爬部分,UIAA I-II 级(T5)",
|
"demanding_alpine_hiking": "相对简单的攀爬部分,UIAA I-II 级(T5)",
|
||||||
"difficult_alpine_hiking": "更长的攀爬部分,UIAA II 级(T6)"
|
"difficult_alpine_hiking": "更长的攀爬部分,UIAA II 级(T6)"
|
||||||
},
|
},
|
||||||
"mtb_scale": "山地地形",
|
"mtb_scale": "山地自行车难度分级",
|
||||||
"error": {
|
"error": {
|
||||||
"from": "起点离最近的道路太远",
|
"from": "起点离最近的道路太远",
|
||||||
"via": "途径点离最近的道路太远",
|
"via": "途径点离最近的道路太远",
|
||||||
@@ -222,9 +222,9 @@
|
|||||||
"remove_gaps": "删除轨迹间的时间间隔",
|
"remove_gaps": "删除轨迹间的时间间隔",
|
||||||
"tooltip": "合并要素",
|
"tooltip": "合并要素",
|
||||||
"help_merge_traces": "连接所选内容并生成一个连续轨迹。",
|
"help_merge_traces": "连接所选内容并生成一个连续轨迹。",
|
||||||
"help_cannot_merge_traces": "须先选择多个文件以合并,",
|
"help_cannot_merge_traces": "须先选择多个文件以合并。",
|
||||||
"help_merge_contents": "合并所选内容并将结果存储于第一个文件。",
|
"help_merge_contents": "合并所选内容并将结果存储于第一个文件。",
|
||||||
"help_cannot_merge_contents": "须先选择多个文件以合并,",
|
"help_cannot_merge_contents": "须先选择多个文件以合并。",
|
||||||
"selection_tip": "可使用 {KEYBOARD_SHORTCUT} 进行多选。"
|
"selection_tip": "可使用 {KEYBOARD_SHORTCUT} 进行多选。"
|
||||||
},
|
},
|
||||||
"extract": {
|
"extract": {
|
||||||
@@ -264,8 +264,8 @@
|
|||||||
"delete_inside": "清除选区内部要素",
|
"delete_inside": "清除选区内部要素",
|
||||||
"delete_outside": "清除选区外部要素",
|
"delete_outside": "清除选区外部要素",
|
||||||
"button": "删除",
|
"button": "删除",
|
||||||
"help": "在地图上绘制矩形选区以清除",
|
"help": "在地图上绘制矩形选区以清除。",
|
||||||
"help_no_selection": "选择一个轨迹以清除其 GPS 点和兴趣点"
|
"help_no_selection": "选择一个轨迹以清除其 GPS 点和兴趣点。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"layers": {
|
"layers": {
|
||||||
@@ -277,7 +277,7 @@
|
|||||||
"new": "新建自定义图层",
|
"new": "新建自定义图层",
|
||||||
"edit": "编辑自定义图层",
|
"edit": "编辑自定义图层",
|
||||||
"urls": "URL(s)",
|
"urls": "URL(s)",
|
||||||
"url_placeholder": "WMTS,WMS 或 MapLibre style JSON",
|
"url_placeholder": "WMTS、WMS 或 MapLibre style JSON",
|
||||||
"max_zoom": "最大缩放等级",
|
"max_zoom": "最大缩放等级",
|
||||||
"layer_type": "图层类型",
|
"layer_type": "图层类型",
|
||||||
"basemap": "底图",
|
"basemap": "底图",
|
||||||
@@ -333,7 +333,7 @@
|
|||||||
"usgs": "USGS",
|
"usgs": "USGS",
|
||||||
"bikerouterGravel": "bikerouter.de Gravel",
|
"bikerouterGravel": "bikerouter.de Gravel",
|
||||||
"cyclOSMlite": "CyclOSM Lite",
|
"cyclOSMlite": "CyclOSM Lite",
|
||||||
"mapterhornHillshade": "山体阴影",
|
"mapterhornHillshade": "Mapterhorn Hillshade",
|
||||||
"openRailwayMap": "OpenRailwayMap",
|
"openRailwayMap": "OpenRailwayMap",
|
||||||
"swisstopoSlope": "Swisstopo Slope",
|
"swisstopoSlope": "Swisstopo Slope",
|
||||||
"swisstopoHiking": "Swisstopo Hiking",
|
"swisstopoHiking": "Swisstopo Hiking",
|
||||||
@@ -377,12 +377,12 @@
|
|||||||
"hut": "小屋",
|
"hut": "小屋",
|
||||||
"picnic": "野餐区",
|
"picnic": "野餐区",
|
||||||
"summit": "顶峰",
|
"summit": "顶峰",
|
||||||
"pass": "关卡",
|
"pass": "山坳",
|
||||||
"climbing": "攀爬",
|
"climbing": "攀爬",
|
||||||
"bicycle": "自行车",
|
"bicycle": "自行车",
|
||||||
"bicycle-parking": "停车区",
|
"bicycle-parking": "自行车停车区",
|
||||||
"bicycle-rental": "出租点",
|
"bicycle-rental": "自行车出租店",
|
||||||
"bicycle-shop": "车店",
|
"bicycle-shop": "自行车店",
|
||||||
"public-transport": "公共交通",
|
"public-transport": "公共交通",
|
||||||
"railway-station": "火车站",
|
"railway-station": "火车站",
|
||||||
"tram-stop": "有轨电车站",
|
"tram-stop": "有轨电车站",
|
||||||
@@ -445,7 +445,7 @@
|
|||||||
"bank": "银行",
|
"bank": "银行",
|
||||||
"beach": "海滩",
|
"beach": "海滩",
|
||||||
"bike_trail": "自行车道",
|
"bike_trail": "自行车道",
|
||||||
"binoculars": "观察点",
|
"binoculars": "望远镜",
|
||||||
"bridge": "桥",
|
"bridge": "桥",
|
||||||
"building": "建筑物",
|
"building": "建筑物",
|
||||||
"campground": "营地",
|
"campground": "营地",
|
||||||
@@ -504,7 +504,7 @@
|
|||||||
"data_visualization": "数据可视化",
|
"data_visualization": "数据可视化",
|
||||||
"data_visualization_description": "可交互的海拔剖面图,带有详细的统计数据,用于分析已记录的活动和规划中的目标。",
|
"data_visualization_description": "可交互的海拔剖面图,带有详细的统计数据,用于分析已记录的活动和规划中的目标。",
|
||||||
"philosophy": "宗旨",
|
"philosophy": "宗旨",
|
||||||
"foss": "免费、 无广告且开源",
|
"foss": "免费、无广告且开源",
|
||||||
"foss_description": "该网站可自由使用,无广告,源代码可在 GitHub 上公开查阅。",
|
"foss_description": "该网站可自由使用,无广告,源代码可在 GitHub 上公开查阅。",
|
||||||
"privacy": "注重隐私",
|
"privacy": "注重隐私",
|
||||||
"privacy_description": "你的 GPX 文件永远不会离开你的浏览器。我们不会跟踪用户的使用行为,也不会收集用户产生的数据。",
|
"privacy_description": "你的 GPX 文件永远不会离开你的浏览器。我们不会跟踪用户的使用行为,也不会收集用户产生的数据。",
|
||||||
|
|||||||
Reference in New Issue
Block a user