32 Commits

Author SHA1 Message Date
vcoppe ef9a5247f0 New translations toolbar.mdx (Ukrainian)
[ci skip]
2026-06-28 16:41:29 +02:00
vcoppe 2418f9bf4d New translations menu.mdx (Ukrainian)
[ci skip]
2026-06-28 16:41:28 +02:00
vcoppe 5263b88fb7 New translations map-controls.mdx (Ukrainian)
[ci skip]
2026-06-28 16:41:27 +02:00
vcoppe b5eb617fbc New translations integration.mdx (Ukrainian)
[ci skip]
2026-06-28 16:41:25 +02:00
vcoppe f15ee2c6cf New translations gpx.mdx (Ukrainian)
[ci skip]
2026-06-28 16:41:24 +02:00
vcoppe 30369cc952 New translations getting-started.mdx (Ukrainian)
[ci skip]
2026-06-28 16:41:23 +02:00
vcoppe 8a089708dc New translations files-and-stats.mdx (Ukrainian)
[ci skip]
2026-06-28 16:41:21 +02:00
vcoppe e3da56e455 New translations faq.mdx (Ukrainian)
[ci skip]
2026-06-28 16:41:20 +02:00
vcoppe bab4910ee0 New translations view.mdx (Ukrainian)
[ci skip]
2026-06-28 16:41:18 +02:00
vcoppe 8301d610cb New translations en.json (Ukrainian)
[ci skip]
2026-06-28 16:41:13 +02:00
vcoppe 6887b7de7e New translations faq.mdx (Ukrainian)
[ci skip]
2026-06-28 15:19:38 +02:00
vcoppe ab4667546a New translations time.mdx (Ukrainian)
[ci skip]
2026-06-28 15:19:37 +02:00
vcoppe 08233c9e25 New translations scissors.mdx (Ukrainian)
[ci skip]
2026-06-28 15:19:35 +02:00
vcoppe be7bdc14b6 New translations routing.mdx (Ukrainian)
[ci skip]
2026-06-28 15:19:34 +02:00
vcoppe 11d488e999 New translations en.json (Ukrainian)
[ci skip]
2026-06-28 15:19:33 +02:00
vcoppe 5f023281b0 New translations elevation.mdx (Ukrainian)
[ci skip]
2026-06-28 14:24:35 +02:00
vcoppe a224ac3dcd New translations poi.mdx (Ukrainian)
[ci skip]
2026-06-28 14:24:34 +02:00
vcoppe 598b2a30fe New translations minify.mdx (Ukrainian)
[ci skip]
2026-06-28 14:24:33 +02:00
vcoppe eb5a71a6f1 New translations merge.mdx (Ukrainian)
[ci skip]
2026-06-28 14:24:31 +02:00
vcoppe e1198d0dc9 New translations extract.mdx (Ukrainian)
[ci skip]
2026-06-28 14:24:30 +02:00
vcoppe 08828d609d New translations routing.mdx (Ukrainian)
[ci skip]
2026-06-28 14:24:29 +02:00
vcoppe 281d5f87c1 New translations clean.mdx (Ukrainian)
[ci skip]
2026-06-28 14:24:28 +02:00
vcoppe 282cfe4dbd New translations en.json (Ukrainian)
[ci skip]
2026-06-28 14:24:27 +02:00
vcoppe 59536ee63a New translations routing.mdx (Ukrainian)
[ci skip]
2026-06-28 13:10:01 +02:00
vcoppe 2dda05f22c New translations clean.mdx (Ukrainian)
[ci skip]
2026-06-28 13:09:59 +02:00
vcoppe 1354ca1d2a New translations view.mdx (Ukrainian)
[ci skip]
2026-06-28 13:09:58 +02:00
vcoppe 94e69c9774 New translations settings.mdx (Ukrainian)
[ci skip]
2026-06-28 13:09:57 +02:00
vcoppe 5a85bc41ea New translations file.mdx (Ukrainian)
[ci skip]
2026-06-28 13:09:55 +02:00
vcoppe bd9e7ea726 New translations file.mdx (Ukrainian)
[ci skip]
2026-06-28 12:04:05 +02:00
vcoppe aa861be53d New translations en.json (Ukrainian)
[ci skip]
2026-06-28 12:04:04 +02:00
vcoppe 52387a40e6 New translations en.json (Hungarian)
[ci skip]
2026-06-25 22:06:50 +02:00
vcoppe dd4c5e17ff New translations en.json (Hungarian)
[ci skip]
2026-06-25 20:51:48 +02:00
31 changed files with 214 additions and 239 deletions
+67 -70
View File
@@ -20,7 +20,7 @@
"immer": "^10.1.1", "immer": "^10.1.1",
"jszip": "^3.10.1", "jszip": "^3.10.1",
"mapillary-js": "^4.1.2", "mapillary-js": "^4.1.2",
"maplibre-gl": "^6.0.0", "maplibre-gl": "^5.21.1",
"sanitize-html": "^2.17.0", "sanitize-html": "^2.17.0",
"sortablejs": "^1.15.6" "sortablejs": "^1.15.6"
}, },
@@ -3236,18 +3236,13 @@
} }
}, },
"node_modules/@mapbox/jsonlint-lines-primitives": { "node_modules/@mapbox/jsonlint-lines-primitives": {
"version": "2.0.3", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.3.tgz",
"integrity": "sha512-0SElaV0uMxEnxzBhhX9WTuPyUeMsAN/SS0i16tjuba4/mio63MG9khjC1a0JAiPGXAwvwm4UfHJURCN7nyudQg==",
"license": "MIT",
"engines": { "engines": {
"node": ">= 22" "node": ">= 0.6"
} }
}, },
"node_modules/@mapbox/point-geometry": { "node_modules/@mapbox/point-geometry": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-1.1.0.tgz",
"integrity": "sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ==",
"license": "ISC" "license": "ISC"
}, },
"node_modules/@mapbox/sphericalmercator": { "node_modules/@mapbox/sphericalmercator": {
@@ -3258,32 +3253,24 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@mapbox/tiny-sdf": { "node_modules/@mapbox/tiny-sdf": {
"version": "2.2.0", "version": "2.0.7",
"resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.2.0.tgz",
"integrity": "sha512-LVL4wgI9YAum5V+LNVQO6QgFBPw7/MIIY4XJPNsPDMrjEwcE+JfKk1LuIl8GnF197ejVdC9QdPaxrx5gfgdGXg==",
"license": "BSD-2-Clause" "license": "BSD-2-Clause"
}, },
"node_modules/@mapbox/unitbezier": { "node_modules/@mapbox/unitbezier": {
"version": "1.0.0", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-1.0.0.tgz",
"integrity": "sha512-fqd515fjBmANKGGsQ286E2Wvj/XvDFpGzwJxq4CI6jMQue6Oy04uCKp+JWKF00xRTmk6cEu1jPJ9p3xqH8YWqQ==",
"license": "BSD-2-Clause" "license": "BSD-2-Clause"
}, },
"node_modules/@mapbox/vector-tile": { "node_modules/@mapbox/vector-tile": {
"version": "3.0.0", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/@mapbox/vector-tile/-/vector-tile-3.0.0.tgz",
"integrity": "sha512-Qf10S1uIHMk20ri/IVBnpS+esUEkVaR5Hftmz88jTInrpmWgPGJfPe3LVjjlE77trLx8tH6qjTG7uWH9hIq/0Q==",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"@mapbox/point-geometry": "~1.1.0", "@mapbox/point-geometry": "~1.1.0",
"@types/geojson": "^7946.0.16", "@types/geojson": "^7946.0.16",
"pbf": "^5.0.0" "pbf": "^4.0.1"
} }
}, },
"node_modules/@mapbox/vector-tile/node_modules/pbf": { "node_modules/@mapbox/vector-tile/node_modules/pbf": {
"version": "5.1.2", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/pbf/-/pbf-5.1.2.tgz",
"integrity": "sha512-mnvGdvOrIvJOBGUEdGkrVXjN8E/VkIJCkf2eS1DH2yv82ORUlLttmDt0rWY38yYZmVwciZwBUvHM20qxBZf40w==",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"resolve-protobuf-schema": "^2.1.0" "resolve-protobuf-schema": "^2.1.0"
@@ -3292,13 +3279,18 @@
"pbf": "bin/pbf" "pbf": "bin/pbf"
} }
}, },
"node_modules/@mapbox/whoots-js": {
"version": "3.1.0",
"license": "ISC",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@maplibre/geojson-vt": { "node_modules/@maplibre/geojson-vt": {
"version": "6.1.1", "version": "6.0.4",
"resolved": "https://registry.npmjs.org/@maplibre/geojson-vt/-/geojson-vt-6.1.1.tgz",
"integrity": "sha512-FVMOcmSP/yqol45t7StApEyTL5/vmqBCuFhH9n+fFuINenhaX+YgHHIt1yJ86S8kln3uJLcMvmEU2cfn6E2eCQ==",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"kdbush": "^4.1.0" "kdbush": "^4.0.2"
} }
}, },
"node_modules/@maplibre/maplibre-gl-geocoder": { "node_modules/@maplibre/maplibre-gl-geocoder": {
@@ -3319,16 +3311,15 @@
} }
}, },
"node_modules/@maplibre/maplibre-gl-style-spec": { "node_modules/@maplibre/maplibre-gl-style-spec": {
"version": "26.2.1", "version": "24.8.1",
"resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-26.2.1.tgz",
"integrity": "sha512-QFKCXkOeSzOr8jF75jm6kySOg+dUvOehPhRi68gcOYPHb7U5JloUq0dJW0Y5/fZV8ygfT0Vp2RWodvq+fyxFWA==",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@mapbox/jsonlint-lines-primitives": "^2.0.3", "@mapbox/jsonlint-lines-primitives": "~2.0.2",
"@mapbox/unitbezier": "^1.0.0", "@mapbox/unitbezier": "^0.0.1",
"json-stringify-pretty-compact": "^4.0.0", "json-stringify-pretty-compact": "^4.0.0",
"minimist": "^1.2.8", "minimist": "^1.2.8",
"quickselect": "^3.0.0", "quickselect": "^3.0.0",
"rw": "^1.3.3",
"tinyqueue": "^3.0.0" "tinyqueue": "^3.0.0"
}, },
"bin": { "bin": {
@@ -3338,29 +3329,31 @@
} }
}, },
"node_modules/@maplibre/mlt": { "node_modules/@maplibre/mlt": {
"version": "1.1.12", "version": "1.1.8",
"resolved": "https://registry.npmjs.org/@maplibre/mlt/-/mlt-1.1.12.tgz",
"integrity": "sha512-ZeK5w2TTeHOajcLaEQs1KZXw2V9wIKo1PmThlxlsHoXsQsYlBqLJzPOd6tJHRtGTChUY3DPPmjXRArYVvAbmZw==",
"license": "(MIT OR Apache-2.0)", "license": "(MIT OR Apache-2.0)",
"dependencies": { "dependencies": {
"@mapbox/point-geometry": "^1.1.0" "@mapbox/point-geometry": "^1.1.0"
} }
}, },
"node_modules/@maplibre/vt-pbf": { "node_modules/@maplibre/vt-pbf": {
"version": "4.3.2", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/@maplibre/vt-pbf/-/vt-pbf-4.3.2.tgz",
"integrity": "sha512-j6p0AdjvAR19Z3XaCysle7A4ZSo08tYOzxD0Y9NQylwPAkwJJeYub5b2eVucdeDh7erhv69DahoLOevDRERRUw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@mapbox/point-geometry": "^1.1.0", "@mapbox/point-geometry": "^1.1.0",
"@mapbox/vector-tile": "^2.0.4",
"@maplibre/geojson-vt": "^5.0.4",
"@types/geojson": "^7946.0.16", "@types/geojson": "^7946.0.16",
"pbf": "^5.1.0" "@types/supercluster": "^7.1.3",
"pbf": "^4.0.1",
"supercluster": "^8.0.1"
} }
}, },
"node_modules/@maplibre/vt-pbf/node_modules/@maplibre/geojson-vt": {
"version": "5.0.4",
"license": "ISC"
},
"node_modules/@maplibre/vt-pbf/node_modules/pbf": { "node_modules/@maplibre/vt-pbf/node_modules/pbf": {
"version": "5.1.2", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/pbf/-/pbf-5.1.2.tgz",
"integrity": "sha512-mnvGdvOrIvJOBGUEdGkrVXjN8E/VkIJCkf2eS1DH2yv82ORUlLttmDt0rWY38yYZmVwciZwBUvHM20qxBZf40w==",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"resolve-protobuf-schema": "^2.1.0" "resolve-protobuf-schema": "^2.1.0"
@@ -4296,6 +4289,13 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/supercluster": {
"version": "7.1.3",
"license": "MIT",
"dependencies": {
"@types/geojson": "*"
}
},
"node_modules/@types/three": { "node_modules/@types/three": {
"version": "0.134.0", "version": "0.134.0",
"license": "MIT" "license": "MIT"
@@ -5720,8 +5720,6 @@
}, },
"node_modules/json-stringify-pretty-compact": { "node_modules/json-stringify-pretty-compact": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-4.0.0.tgz",
"integrity": "sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/jszip": { "node_modules/jszip": {
@@ -5735,9 +5733,7 @@
} }
}, },
"node_modules/kdbush": { "node_modules/kdbush": {
"version": "4.1.0", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.1.0.tgz",
"integrity": "sha512-e9vurzrXJQrFX6ckpHP3bvj5l+9CnYzkxDNnNQ1h2QTqdWsUAJgXiKdGNcOa1EY85dU8KbQ+z/FdQdB7P+9yfQ==",
"license": "ISC" "license": "ISC"
}, },
"node_modules/keyv": { "node_modules/keyv": {
@@ -6158,25 +6154,25 @@
"license": "(MIT AND Zlib)" "license": "(MIT AND Zlib)"
}, },
"node_modules/maplibre-gl": { "node_modules/maplibre-gl": {
"version": "6.0.0", "version": "5.22.0",
"resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-6.0.0.tgz",
"integrity": "sha512-1wBgEhzTZfA+cDpFdt0fM1mJA5mJ90fifORJ7D8JcKLJCvPT/iTx9bNxkP7DqEYde65DJd7gE7h83khwNRqdyg==",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"@mapbox/jsonlint-lines-primitives": "^2.0.2",
"@mapbox/point-geometry": "^1.1.0", "@mapbox/point-geometry": "^1.1.0",
"@mapbox/tiny-sdf": "^2.2.0", "@mapbox/tiny-sdf": "^2.0.7",
"@mapbox/unitbezier": "^1.0.0", "@mapbox/unitbezier": "^0.0.1",
"@mapbox/vector-tile": "^3.0.0", "@mapbox/vector-tile": "^2.0.4",
"@maplibre/geojson-vt": "^6.1.1", "@mapbox/whoots-js": "^3.1.0",
"@maplibre/maplibre-gl-style-spec": "^26.1.0", "@maplibre/geojson-vt": "^6.0.4",
"@maplibre/mlt": "^1.1.12", "@maplibre/maplibre-gl-style-spec": "^24.8.1",
"@maplibre/vt-pbf": "^4.3.2", "@maplibre/mlt": "^1.1.8",
"@maplibre/vt-pbf": "^4.3.0",
"@types/geojson": "^7946.0.16", "@types/geojson": "^7946.0.16",
"earcut": "^3.2.3", "earcut": "^3.0.2",
"gl-matrix": "^3.4.4", "gl-matrix": "^3.4.4",
"kdbush": "^4.1.0", "kdbush": "^4.0.2",
"murmurhash-js": "^1.0.0", "murmurhash-js": "^1.0.0",
"pbf": "^5.1.2", "pbf": "^4.0.1",
"potpack": "^2.1.0", "potpack": "^2.1.0",
"quickselect": "^3.0.0", "quickselect": "^3.0.0",
"tinyqueue": "^3.0.0" "tinyqueue": "^3.0.0"
@@ -6190,15 +6186,11 @@
} }
}, },
"node_modules/maplibre-gl/node_modules/earcut": { "node_modules/maplibre-gl/node_modules/earcut": {
"version": "3.2.3", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/earcut/-/earcut-3.2.3.tgz",
"integrity": "sha512-vnS4AVwp1KHAF13i1vp1/2D5evWy3k5u/iW/B81QVsUZtV8cv2tU0b2VNFlqvh4kYwrFMDdjPCfAmfyJW9y14Q==",
"license": "ISC" "license": "ISC"
}, },
"node_modules/maplibre-gl/node_modules/pbf": { "node_modules/maplibre-gl/node_modules/pbf": {
"version": "5.1.2", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/pbf/-/pbf-5.1.2.tgz",
"integrity": "sha512-mnvGdvOrIvJOBGUEdGkrVXjN8E/VkIJCkf2eS1DH2yv82ORUlLttmDt0rWY38yYZmVwciZwBUvHM20qxBZf40w==",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"resolve-protobuf-schema": "^2.1.0" "resolve-protobuf-schema": "^2.1.0"
@@ -6259,8 +6251,6 @@
}, },
"node_modules/minimist": { "node_modules/minimist": {
"version": "1.2.8", "version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
"license": "MIT", "license": "MIT",
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
@@ -6795,8 +6785,6 @@
}, },
"node_modules/quickselect": { "node_modules/quickselect": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz",
"integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==",
"license": "ISC" "license": "ISC"
}, },
"node_modules/rbush": { "node_modules/rbush": {
@@ -6932,6 +6920,10 @@
} }
} }
}, },
"node_modules/rw": {
"version": "1.3.3",
"license": "BSD-3-Clause"
},
"node_modules/rxjs": { "node_modules/rxjs": {
"version": "7.8.2", "version": "7.8.2",
"license": "Apache-2.0", "license": "Apache-2.0",
@@ -7165,6 +7157,13 @@
"xtend": "^4.0.0" "xtend": "^4.0.0"
} }
}, },
"node_modules/supercluster": {
"version": "8.0.1",
"license": "ISC",
"dependencies": {
"kdbush": "^4.0.2"
}
},
"node_modules/supports-color": { "node_modules/supports-color": {
"version": "7.2.0", "version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -7406,8 +7405,6 @@
}, },
"node_modules/tinyqueue": { "node_modules/tinyqueue": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-3.0.0.tgz",
"integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==",
"license": "ISC" "license": "ISC"
}, },
"node_modules/totalist": { "node_modules/totalist": {
+1 -1
View File
@@ -75,7 +75,7 @@
"immer": "^10.1.1", "immer": "^10.1.1",
"jszip": "^3.10.1", "jszip": "^3.10.1",
"mapillary-js": "^4.1.2", "mapillary-js": "^4.1.2",
"maplibre-gl": "^6.0.0", "maplibre-gl": "^5.21.1",
"sanitize-html": "^2.17.0", "sanitize-html": "^2.17.0",
"sortablejs": "^1.15.6" "sortablejs": "^1.15.6"
} }
+1 -1
View File
@@ -1168,7 +1168,7 @@ export type CustomLayer = {
maxZoom: number; maxZoom: number;
layerType: 'basemap' | 'overlay'; layerType: 'basemap' | 'overlay';
resourceType: 'raster' | 'vector'; resourceType: 'raster' | 'vector';
value: string | StyleSpecification; value: string | maplibregl.StyleSpecification;
}; };
type OverpassQueryData = { type OverpassQueryData = {
@@ -21,7 +21,6 @@
import { selection } from '$lib/logic/selection'; import { selection } from '$lib/logic/selection';
import { untrack } from 'svelte'; import { untrack } from 'svelte';
import { isSelected, toggle } from '$lib/components/map/layer-control/utils'; import { isSelected, toggle } from '$lib/components/map/layer-control/utils';
import { boundsManager } from '$lib/logic/bounds';
let { let {
useHash = true, useHash = true,
@@ -91,7 +90,6 @@
fileStateCollection.setEmbeddedFiles(files); fileStateCollection.setEmbeddedFiles(files);
$fileOrder = ids; $fileOrder = ids;
selection.selectAll(); selection.selectAll();
boundsManager.fitBoundsOnLoad(ids);
}); });
} }
@@ -2,7 +2,6 @@
import CustomControl from './custom-control'; import CustomControl from './custom-control';
import { map } from '$lib/components/map/map'; import { map } from '$lib/components/map/map';
import { onMount, type Snippet } from 'svelte'; import { onMount, type Snippet } from 'svelte';
import type { Map } from 'maplibre-gl';
let { let {
position = 'top-right', position = 'top-right',
@@ -18,7 +17,7 @@
let control: CustomControl | null = null; let control: CustomControl | null = null;
onMount(() => { onMount(() => {
map.onLoad((map: Map) => { map.onLoad((map: maplibregl.Map) => {
if (position.includes('right')) container.classList.add('float-right'); if (position.includes('right')) container.classList.add('float-right');
else container.classList.add('float-left'); else container.classList.add('float-left');
container.classList.remove('hidden'); container.classList.remove('hidden');
@@ -1,10 +1,9 @@
import { MapPopup } from '$lib/components/map/map-popup'; import { MapPopup } from '$lib/components/map/map-popup';
import type { Map } from 'maplibre-gl';
export let waypointPopup: MapPopup | null = null; export let waypointPopup: MapPopup | null = null;
export let trackpointPopup: MapPopup | null = null; export let trackpointPopup: MapPopup | null = null;
export function createPopups(map: Map) { export function createPopups(map: maplibregl.Map) {
removePopups(); removePopups();
waypointPopup = new MapPopup(map, { waypointPopup = new MapPopup(map, {
closeButton: false, closeButton: false,
@@ -1,10 +1,9 @@
import { get, type Readable } from 'svelte/store'; import { get, type Readable } from 'svelte/store';
import { import maplibregl, {
type GeoJSONSource, type GeoJSONSource,
type FilterSpecification, type FilterSpecification,
type MapLayerMouseEvent, type MapLayerMouseEvent,
type MapLayerTouchEvent, type MapLayerTouchEvent,
Point,
} from 'maplibre-gl'; } from 'maplibre-gl';
import { map } from '$lib/components/map/map'; import { map } from '$lib/components/map/map';
import { waypointPopup, trackpointPopup } from './gpx-layer-popup'; import { waypointPopup, trackpointPopup } from './gpx-layer-popup';
@@ -121,7 +120,7 @@ export class GPXLayer {
selected: boolean = false; selected: boolean = false;
currentWaypointData: GeoJSON.FeatureCollection | null = null; currentWaypointData: GeoJSON.FeatureCollection | null = null;
draggedWaypointIndex: number | null = null; draggedWaypointIndex: number | null = null;
draggingStartingPosition: Point = new Point(0, 0); draggingStartingPosition: maplibregl.Point = new maplibregl.Point(0, 0);
unsubscribe: Function[] = []; unsubscribe: Function[] = [];
updateBinded: () => void = this.update.bind(this); updateBinded: () => void = this.update.bind(this);
@@ -7,7 +7,6 @@
import { Layers } from '@lucide/svelte'; import { Layers } from '@lucide/svelte';
import { settings } from '$lib/logic/settings'; import { settings } from '$lib/logic/settings';
import { map } from '$lib/components/map/map'; import { map } from '$lib/components/map/map';
import type { Map } from 'maplibre-gl';
let container: HTMLDivElement; let container: HTMLDivElement;
let overpassLayer: OverpassLayer; let overpassLayer: OverpassLayer;
@@ -22,7 +21,7 @@
selectedOverpassTree, selectedOverpassTree,
} = settings; } = settings;
map.onLoad((_map: Map) => { map.onLoad((_map: maplibregl.Map) => {
if (overpassLayer) { if (overpassLayer) {
overpassLayer.remove(); overpassLayer.remove();
} }
@@ -15,9 +15,7 @@
poi: PopupItem<any>; poi: PopupItem<any>;
} = $props(); } = $props();
let tags: Record<string, string> = $derived( let tags: Record<string, string> = $derived(poi ? JSON.parse(poi.item.tags) : {});
poi ? (typeof poi.item.tags == 'object' ? poi.item.tags : JSON.parse(poi.item.tags)) : {}
);
let name = $derived.by(() => { let name = $derived.by(() => {
if (poi) { if (poi) {
if (tags.name !== undefined && tags.name !== '') { if (tags.name !== undefined && tags.name !== '') {
@@ -6,7 +6,7 @@ import { overpassQueryData } from '$lib/assets/layers';
import { MapPopup } from '$lib/components/map/map-popup'; import { MapPopup } from '$lib/components/map/map-popup';
import { settings } from '$lib/logic/settings'; import { settings } from '$lib/logic/settings';
import { db } from '$lib/db'; import { db } from '$lib/db';
import type { Map as MapLibreMap, GeoJSONSource } from 'maplibre-gl'; import type { GeoJSONSource } from 'maplibre-gl';
import { ANCHOR_LAYER_KEY } from '$lib/components/map/style'; import { ANCHOR_LAYER_KEY } from '$lib/components/map/style';
import type { MapLayerEventManager } from '$lib/components/map/map-layer-event-manager'; import type { MapLayerEventManager } from '$lib/components/map/map-layer-event-manager';
import { loadSVGIcon } from '$lib/utils'; import { loadSVGIcon } from '$lib/utils';
@@ -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: MapLibreMap; map: maplibregl.Map;
layerEventManager: MapLayerEventManager; layerEventManager: MapLayerEventManager;
popup: MapPopup; popup: MapPopup;
@@ -40,7 +40,7 @@ export class OverpassLayer {
updateBinded = this.update.bind(this); updateBinded = this.update.bind(this);
onHoverBinded = this.onHover.bind(this); onHoverBinded = this.onHover.bind(this);
constructor(map: MapLibreMap, layerEventManager: MapLayerEventManager) { constructor(map: maplibregl.Map, layerEventManager: MapLayerEventManager) {
this.map = map; this.map = map;
this.layerEventManager = layerEventManager; this.layerEventManager = layerEventManager;
this.popup = new MapPopup(map, { this.popup = new MapPopup(map, {
@@ -1,19 +1,10 @@
import { fileStateCollection } from '$lib/logic/file-state'; import { fileStateCollection } from '$lib/logic/file-state';
import { import maplibregl from 'maplibre-gl';
LngLatBounds,
MapMouseEvent,
MapTouchEvent,
Point,
type Map,
type MapGeoJSONFeature,
type MapLayerMouseEvent,
type MapLayerTouchEvent,
} from 'maplibre-gl';
type MapLayerMouseEventListener = (e: MapLayerMouseEvent) => void; type MapLayerMouseEventListener = (e: maplibregl.MapLayerMouseEvent) => void;
type MapLayerTouchEventListener = (e: MapLayerTouchEvent) => void; type MapLayerTouchEventListener = (e: maplibregl.MapLayerTouchEvent) => void;
type MapLayerListener = { type MapLayerListener = {
features: MapGeoJSONFeature[]; features: maplibregl.MapGeoJSONFeature[];
mousemoves: MapLayerMouseEventListener[]; mousemoves: MapLayerMouseEventListener[];
mouseenters: MapLayerMouseEventListener[]; mouseenters: MapLayerMouseEventListener[];
mouseleaves: MapLayerMouseEventListener[]; mouseleaves: MapLayerMouseEventListener[];
@@ -24,10 +15,10 @@ type MapLayerListener = {
}; };
export class MapLayerEventManager { export class MapLayerEventManager {
private _map: Map; private _map: maplibregl.Map;
private _listeners: Record<string, MapLayerListener> = {}; private _listeners: Record<string, MapLayerListener> = {};
constructor(map: Map) { constructor(map: maplibregl.Map) {
this._map = map; this._map = map;
this._map.on('mousemove', this._handleMouseMove.bind(this)); this._map.on('mousemove', this._handleMouseMove.bind(this));
this._map.on('click', this._handleMouseClick.bind(this, 'click')); this._map.on('click', this._handleMouseClick.bind(this, 'click'));
@@ -150,7 +141,7 @@ export class MapLayerEventManager {
} }
} }
private _handleMouseMove(e: MapMouseEvent) { private _handleMouseMove(e: maplibregl.MapMouseEvent) {
if (e.originalEvent.buttons > 0) return; if (e.originalEvent.buttons > 0) return;
const featuresByLayer = this._getRenderedFeaturesByLayer(e); const featuresByLayer = this._getRenderedFeaturesByLayer(e);
Object.keys(this._listeners).forEach((layerId) => { Object.keys(this._listeners).forEach((layerId) => {
@@ -159,20 +150,29 @@ export class MapLayerEventManager {
if ((features.length == 0) != (listener.features.length == 0)) { if ((features.length == 0) != (listener.features.length == 0)) {
if (features.length > 0) { if (features.length > 0) {
if (listener.mouseenters.length > 0) { if (listener.mouseenters.length > 0) {
const event = new MapMouseEvent('mouseenter', e.target, e.originalEvent, { const event = new maplibregl.MapMouseEvent(
features: featuresByLayer[layerId]!, 'mouseenter',
}); e.target,
e.originalEvent,
{
features: featuresByLayer[layerId]!,
}
);
listener.mouseenters.forEach((l) => l(event)); listener.mouseenters.forEach((l) => l(event));
} }
} else { } else {
if (listener.mouseleaves.length > 0) { if (listener.mouseleaves.length > 0) {
const event = new MapMouseEvent('mouseleave', e.target, e.originalEvent); const event = new maplibregl.MapMouseEvent(
'mouseleave',
e.target,
e.originalEvent
);
listener.mouseleaves.forEach((l) => l(event)); listener.mouseleaves.forEach((l) => l(event));
} }
} }
} }
if (features.length > 0 && listener.mousemoves.length > 0) { if (features.length > 0 && listener.mousemoves.length > 0) {
const event = new MapMouseEvent('mousemove', e.target, e.originalEvent, { const event = new maplibregl.MapMouseEvent('mousemove', e.target, e.originalEvent, {
features: featuresByLayer[layerId]!, features: featuresByLayer[layerId]!,
}); });
listener.mousemoves.forEach((l) => l(event)); listener.mousemoves.forEach((l) => l(event));
@@ -181,39 +181,49 @@ export class MapLayerEventManager {
}); });
} }
private _handleMouseClick(type: string, e: MapMouseEvent) { private _handleMouseClick(type: string, e: maplibregl.MapMouseEvent) {
const featuresByLayer = this._getRenderedFeaturesByLayer(e); const featuresByLayer = this._getRenderedFeaturesByLayer(e);
Object.keys(this._listeners).forEach((layerId) => { Object.keys(this._listeners).forEach((layerId) => {
const features = featuresByLayer[layerId] || []; const features = featuresByLayer[layerId] || [];
const listener = this._listeners[layerId]; const listener = this._listeners[layerId];
if (features.length > 0) { if (features.length > 0) {
if (type === 'click' && listener.clicks.length > 0) { if (type === 'click' && listener.clicks.length > 0) {
const event = new MapMouseEvent('click', e.target, e.originalEvent, { const event = new maplibregl.MapMouseEvent('click', e.target, e.originalEvent, {
features: features, features: features,
}); });
listener.clicks.forEach((l) => l(event)); listener.clicks.forEach((l) => l(event));
} else if (type === 'contextmenu' && listener.contextmenus.length > 0) { } else if (type === 'contextmenu' && listener.contextmenus.length > 0) {
const event = new MapMouseEvent('contextmenu', e.target, e.originalEvent, { const event = new maplibregl.MapMouseEvent(
features: features, 'contextmenu',
}); e.target,
e.originalEvent,
{
features: features,
}
);
listener.contextmenus.forEach((l) => l(event)); listener.contextmenus.forEach((l) => l(event));
} else if (type === 'mousedown' && listener.mousedowns.length > 0) { } else if (type === 'mousedown' && listener.mousedowns.length > 0) {
const event = new MapMouseEvent('mousedown', e.target, e.originalEvent, { const event = new maplibregl.MapMouseEvent(
features: features, 'mousedown',
}); e.target,
e.originalEvent,
{
features: features,
}
);
listener.mousedowns.forEach((l) => l(event)); listener.mousedowns.forEach((l) => l(event));
} }
} }
}); });
} }
private _handleTouchStart(e: MapTouchEvent) { private _handleTouchStart(e: maplibregl.MapTouchEvent) {
const featuresByLayer = this._getRenderedFeaturesByLayer(e); const featuresByLayer = this._getRenderedFeaturesByLayer(e);
Object.keys(this._listeners).forEach((layerId) => { Object.keys(this._listeners).forEach((layerId) => {
const features = featuresByLayer[layerId] || []; const features = featuresByLayer[layerId] || [];
const listener = this._listeners[layerId]; const listener = this._listeners[layerId];
if (features.length > 0) { if (features.length > 0) {
const event: MapLayerTouchEvent = new MapTouchEvent( const event: maplibregl.MapLayerTouchEvent = new maplibregl.MapTouchEvent(
'touchstart', 'touchstart',
e.target, e.target,
e.originalEvent e.originalEvent
@@ -224,15 +234,18 @@ export class MapLayerEventManager {
}); });
} }
private _getBounds(point: Point) { private _getBounds(point: maplibregl.Point) {
const delta = 30; const delta = 30;
return new LngLatBounds( return new maplibregl.LngLatBounds(
this._map.unproject([point.x - delta, point.y + delta]), this._map.unproject([point.x - delta, point.y + delta]),
this._map.unproject([point.x + delta, point.y - delta]) this._map.unproject([point.x + delta, point.y - delta])
); );
} }
private _filterLayersIntersectingBounds(layerIds: string[], bounds: LngLatBounds): string[] { private _filterLayersIntersectingBounds(
layerIds: string[],
bounds: maplibregl.LngLatBounds
): string[] {
let result = layerIds.filter((layerId) => { let result = layerIds.filter((layerId) => {
if (!this._map.getLayer(layerId)) return false; if (!this._map.getLayer(layerId)) return false;
const fileId = layerId.replace('-waypoints', ''); const fileId = layerId.replace('-waypoints', '');
@@ -248,7 +261,7 @@ export class MapLayerEventManager {
return result; return result;
} }
private _getRenderedFeaturesByLayer(e: MapMouseEvent | MapTouchEvent) { private _getRenderedFeaturesByLayer(e: maplibregl.MapMouseEvent | maplibregl.MapTouchEvent) {
const layerIds = this._filterLayersIntersectingBounds( const layerIds = this._filterLayersIntersectingBounds(
Object.keys(this._listeners), Object.keys(this._listeners),
this._getBounds(e.point) this._getBounds(e.point)
@@ -257,7 +270,7 @@ export class MapLayerEventManager {
layerIds.length > 0 layerIds.length > 0
? this._map.queryRenderedFeatures(e.point, { layers: layerIds }) ? this._map.queryRenderedFeatures(e.point, { layers: layerIds })
: []; : [];
const featuresByLayer: Record<string, MapGeoJSONFeature[]> = {}; const featuresByLayer: Record<string, maplibregl.MapGeoJSONFeature[]> = {};
features.forEach((f) => { features.forEach((f) => {
if (!featuresByLayer[f.layer.id]) { if (!featuresByLayer[f.layer.id]) {
featuresByLayer[f.layer.id] = []; featuresByLayer[f.layer.id] = [];
+8 -8
View File
@@ -1,5 +1,5 @@
import { TrackPoint, Waypoint } from 'gpx'; import { TrackPoint, Waypoint } from 'gpx';
import { LngLat, Map, MapMouseEvent, Popup, type PopupOptions } from 'maplibre-gl'; import maplibregl from 'maplibre-gl';
import { mount, tick, unmount } from 'svelte'; import { mount, tick, unmount } from 'svelte';
import { get, writable, type Writable } from 'svelte/store'; import { get, writable, type Writable } from 'svelte/store';
import MapPopupComponent from '$lib/components/map/MapPopup.svelte'; import MapPopupComponent from '$lib/components/map/MapPopup.svelte';
@@ -11,15 +11,15 @@ export type PopupItem<T = Waypoint | TrackPoint | any> = {
}; };
export class MapPopup { export class MapPopup {
map: Map; map: maplibregl.Map;
popup: Popup; popup: maplibregl.Popup;
item: Writable<PopupItem | null> = writable(null); item: Writable<PopupItem | null> = writable(null);
component: ReturnType<typeof mount>; component: ReturnType<typeof mount>;
maybeHideBinded = this.maybeHide.bind(this); maybeHideBinded = this.maybeHide.bind(this);
constructor(map: Map, options?: PopupOptions) { constructor(map: maplibregl.Map, options?: maplibregl.PopupOptions) {
this.map = map; this.map = map;
this.popup = new Popup(options); this.popup = new maplibregl.Popup(options);
this.component = mount(MapPopupComponent, { this.component = mount(MapPopupComponent, {
target: document.body, target: document.body,
props: { props: {
@@ -51,7 +51,7 @@ export class MapPopup {
this.map.on('mousemove', this.maybeHideBinded); this.map.on('mousemove', this.maybeHideBinded);
} }
maybeHide(e: MapMouseEvent) { maybeHide(e: maplibregl.MapMouseEvent) {
const item = get(this.item); const item = get(this.item);
if (item === null) { if (item === null) {
this.hide(); this.hide();
@@ -75,10 +75,10 @@ export class MapPopup {
getCoordinates() { getCoordinates() {
const item = get(this.item); const item = get(this.item);
if (item === null) { if (item === null) {
return new LngLat(0, 0); return new maplibregl.LngLat(0, 0);
} }
return item.item instanceof Waypoint || item.item instanceof TrackPoint return item.item instanceof Waypoint || item.item instanceof TrackPoint
? item.item.getCoordinates() ? item.item.getCoordinates()
: new LngLat(item.item.lon, item.item.lat); : new maplibregl.LngLat(item.item.lon, item.item.lat);
} }
} }
+1 -3
View File
@@ -1,6 +1,5 @@
import * as maplibregl from 'maplibre-gl'; import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css'; import 'maplibre-gl/dist/maplibre-gl.css';
import workerUrl from 'maplibre-gl/dist/maplibre-gl-worker.mjs?worker&url';
import MaplibreGeocoder, { import MaplibreGeocoder, {
type MaplibreGeocoderFeatureResults, type MaplibreGeocoderFeatureResults,
} from '@maplibre/maplibre-gl-geocoder'; } from '@maplibre/maplibre-gl-geocoder';
@@ -40,7 +39,6 @@ export class MapLibreGLMap {
geocoder: boolean, geocoder: boolean,
geolocate: boolean geolocate: boolean
) { ) {
maplibregl.setWorkerUrl(workerUrl);
this._maptilerKey = maptilerKey; this._maptilerKey = maptilerKey;
this._styleManager = new StyleManager(this._mapStore, this._maptilerKey); this._styleManager = new StyleManager(this._mapStore, this._maptilerKey);
const map = new maplibregl.Map({ const map = new maplibregl.Map({
@@ -9,7 +9,6 @@
import { i18n } from '$lib/i18n.svelte'; import { i18n } from '$lib/i18n.svelte';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import ButtonWithTooltip from '$lib/components/ButtonWithTooltip.svelte'; import ButtonWithTooltip from '$lib/components/ButtonWithTooltip.svelte';
import type { Map } from 'maplibre-gl';
const { streetViewSource } = settings; const { streetViewSource } = settings;
@@ -21,7 +20,7 @@
let container: HTMLElement; let container: HTMLElement;
onMount(() => { onMount(() => {
map.onLoad((map_: Map) => { map.onLoad((map_: maplibregl.Map) => {
googleRedirect = new GoogleRedirect(map_); googleRedirect = new GoogleRedirect(map_);
mapillaryLayer = new MapillaryLayer( mapillaryLayer = new MapillaryLayer(
map_, map_,
@@ -1,11 +1,10 @@
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor'; import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
import type { Map, MapMouseEvent } from 'maplibre-gl';
export class GoogleRedirect { export class GoogleRedirect {
map: Map; map: maplibregl.Map;
enabled = false; enabled = false;
constructor(map: Map) { constructor(map: maplibregl.Map) {
this.map = map; this.map = map;
} }
@@ -25,7 +24,7 @@ export class GoogleRedirect {
this.map.off('click', this.openStreetView); this.map.off('click', this.openStreetView);
} }
openStreetView(e: MapMouseEvent) { openStreetView(e: maplibregl.MapMouseEvent) {
window.open( window.open(
`https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=${e.lngLat.lat},${e.lngLat.lng}` `https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=${e.lngLat.lat},${e.lngLat.lng}`
); );
@@ -1,10 +1,4 @@
import { import maplibregl, { type LayerSpecification, type VectorSourceSpecification } from 'maplibre-gl';
Map,
Marker,
type LayerSpecification,
type MapLayerMouseEvent,
type VectorSourceSpecification,
} from 'maplibre-gl';
import { Viewer, type ViewerBearingEvent } from 'mapillary-js/dist/mapillary.module'; import { Viewer, type ViewerBearingEvent } from 'mapillary-js/dist/mapillary.module';
import 'mapillary-js/dist/mapillary.css'; import 'mapillary-js/dist/mapillary.css';
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor'; import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
@@ -49,9 +43,9 @@ const mapillaryImageLayer: LayerSpecification = {
}; };
export class MapillaryLayer { export class MapillaryLayer {
map: Map; map: maplibregl.Map;
layerEventManager: MapLayerEventManager; layerEventManager: MapLayerEventManager;
marker: Marker; marker: maplibregl.Marker;
viewer: Viewer; viewer: Viewer;
active = false; active = false;
@@ -62,7 +56,7 @@ export class MapillaryLayer {
onMouseLeaveBinded = this.onMouseLeave.bind(this); onMouseLeaveBinded = this.onMouseLeave.bind(this);
constructor( constructor(
map: Map, map: maplibregl.Map,
layerEventManager: MapLayerEventManager, layerEventManager: MapLayerEventManager,
container: HTMLElement, container: HTMLElement,
popupOpen: { value: boolean } popupOpen: { value: boolean }
@@ -81,7 +75,7 @@ export class MapillaryLayer {
dot.className = 'maplibregl-user-location-dot'; dot.className = 'maplibregl-user-location-dot';
element.appendChild(dot); element.appendChild(dot);
this.marker = new Marker({ this.marker = new maplibregl.Marker({
rotationAlignment: 'map', rotationAlignment: 'map',
element, element,
}); });
@@ -146,7 +140,7 @@ export class MapillaryLayer {
this.popupOpen.value = false; this.popupOpen.value = false;
} }
onMouseEnter(e: MapLayerMouseEvent) { onMouseEnter(e: maplibregl.MapLayerMouseEvent) {
if ( if (
e.features && e.features &&
e.features.length > 0 && e.features.length > 0 &&
+11 -16
View File
@@ -9,17 +9,11 @@ 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: GeoJSONSourceSpecification = { const emptySource: maplibregl.GeoJSONSourceSpecification = {
type: 'geojson', type: 'geojson',
data: { data: {
type: 'FeatureCollection', type: 'FeatureCollection',
@@ -38,18 +32,18 @@ export const ANCHOR_LAYER_KEY = {
waypoints: 'waypoints-end', waypoints: 'waypoints-end',
routingControls: 'routing-controls-end', routingControls: 'routing-controls-end',
}; };
const anchorLayers: LayerSpecification[] = Object.values(ANCHOR_LAYER_KEY).map((id) => ({ const anchorLayers: maplibregl.LayerSpecification[] = Object.values(ANCHOR_LAYER_KEY).map((id) => ({
id: id, id: id,
type: 'symbol', type: 'symbol',
source: 'empty-source', source: 'empty-source',
})); }));
export class StyleManager { export class StyleManager {
private _map: Writable<Map | null>; private _map: Writable<maplibregl.Map | null>;
private _maptilerKey: string; private _maptilerKey: string;
private _pastOverlays: Set<string> = new Set(); private _pastOverlays: Set<string> = new Set();
constructor(map: Writable<Map | null>, maptilerKey: string) { constructor(map: Writable<maplibregl.Map | null>, maptilerKey: string) {
this._map = map; this._map = map;
this._maptilerKey = maptilerKey; this._maptilerKey = maptilerKey;
this._map.subscribe((map_) => { this._map.subscribe((map_) => {
@@ -64,7 +58,6 @@ 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'))) {
@@ -82,10 +75,10 @@ export class StyleManager {
}); });
} }
async buildStyle(basemap: string): Promise<StyleSpecification> { async buildStyle(basemap: string): Promise<maplibregl.StyleSpecification> {
const custom = get(customLayers); const custom = get(customLayers);
const style: StyleSpecification = { const style: maplibregl.StyleSpecification = {
version: 8, version: 8,
projection: { projection: {
type: 'globe', type: 'globe',
@@ -98,7 +91,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 StyleSpecification; let basemapStyle = basemaps.openStreetMap as maplibregl.StyleSpecification;
try { try {
basemapStyle = await this.get(basemapInfo); basemapStyle = await this.get(basemapInfo);
for (const source in basemapStyle.sources) { for (const source in basemapStyle.sources) {
@@ -209,7 +202,9 @@ export class StyleManager {
} }
} }
async get(styleInfo: StyleSpecification | string): Promise<StyleSpecification> { async get(
styleInfo: maplibregl.StyleSpecification | string
): Promise<maplibregl.StyleSpecification> {
if (typeof styleInfo === 'string') { if (typeof styleInfo === 'string') {
let styleUrl = styleInfo as string; let styleUrl = styleInfo as string;
const response = await fetch(styleUrl, { cache: 'force-cache' }); const response = await fetch(styleUrl, { cache: 'force-cache' });
@@ -223,7 +218,7 @@ export class StyleManager {
} }
} }
merge(style: StyleSpecification, other: StyleSpecification) { merge(style: maplibregl.StyleSpecification, other: maplibregl.StyleSpecification) {
style.sources = { ...style.sources, ...other.sources }; style.sources = { ...style.sources, ...other.sources };
const units = get(distanceUnits); 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 { Popup } from 'maplibre-gl'; import maplibregl from 'maplibre-gl';
import { settings } from '$lib/logic/settings'; import { settings } from '$lib/logic/settings';
let { let {
@@ -23,11 +23,11 @@
const { minimizeRoutingMenu } = settings; const { minimizeRoutingMenu } = settings;
let popupElement: HTMLDivElement | undefined = $state(undefined); let popupElement: HTMLDivElement | undefined = $state(undefined);
let popup: Popup | undefined = $derived.by(() => { let popup: maplibregl.Popup | undefined = $derived.by(() => {
if (!popupElement) { if (!popupElement) {
return undefined; return undefined;
} }
let popup = new Popup({ let popup = new maplibregl.Popup({
closeButton: false, closeButton: false,
maxWidth: undefined, maxWidth: undefined,
}); });
@@ -16,7 +16,7 @@
import { getURLForLanguage } from '$lib/utils'; import { getURLForLanguage } from '$lib/utils';
import { Trash2 } from '@lucide/svelte'; import { Trash2 } from '@lucide/svelte';
import { map } from '$lib/components/map/map'; import { map } from '$lib/components/map/map';
import type { GeoJSONSource, LngLat } from 'maplibre-gl'; import type { GeoJSONSource } from 'maplibre-gl';
import { selection } from '$lib/logic/selection'; import { selection } from '$lib/logic/selection';
import { fileActions } from '$lib/logic/file-actions'; import { fileActions } from '$lib/logic/file-actions';
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor'; import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
@@ -29,7 +29,7 @@
let cleanType = $state(CleanType.INSIDE); let cleanType = $state(CleanType.INSIDE);
let deleteTrackpoints = $state(true); let deleteTrackpoints = $state(true);
let deleteWaypoints = $state(true); let deleteWaypoints = $state(true);
let rectangleCoordinates: LngLat[] = $state([]); let rectangleCoordinates: maplibregl.LngLat[] = $state([]);
$effect(() => { $effect(() => {
if ($map) { if ($map) {
@@ -41,7 +41,6 @@
import { fileActions, getFileIds, newGPXFile } from '$lib/logic/file-actions'; import { fileActions, getFileIds, newGPXFile } from '$lib/logic/file-actions';
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor'; import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
import { RoutingControls, routingControls } from './routing-controls'; import { RoutingControls, routingControls } from './routing-controls';
import type { Popup } from 'maplibre-gl';
let { let {
minimized = $bindable(false), minimized = $bindable(false),
@@ -52,7 +51,7 @@
}: { }: {
minimized?: boolean; minimized?: boolean;
minimizable?: boolean; minimizable?: boolean;
popup?: Popup; popup?: maplibregl.Popup;
popupElement?: HTMLDivElement; popupElement?: HTMLDivElement;
class?: string; class?: string;
} = $props(); } = $props();
@@ -1,12 +1,10 @@
import { distance, type Coordinates, TrackPoint, TrackSegment, Track, projectedPoint } from 'gpx'; import { distance, type Coordinates, TrackPoint, TrackSegment, Track, projectedPoint } from 'gpx';
import { get, writable, type Readable } from 'svelte/store'; import { get, writable, type Readable } from 'svelte/store';
import { import maplibregl, {
type MapMouseEvent, type MapMouseEvent,
type GeoJSONSource, type GeoJSONSource,
type MapLayerMouseEvent, type MapLayerMouseEvent,
type MapLayerTouchEvent, type MapLayerTouchEvent,
Popup,
Point,
} from 'maplibre-gl'; } from 'maplibre-gl';
import { route } from './routing'; import { route } from './routing';
import { toast } from 'svelte-sonner'; import { toast } from 'svelte-sonner';
@@ -52,7 +50,7 @@ export class RoutingControls {
} }
> = new Map(); > = new Map();
anchors: GeoJSON.Feature<GeoJSON.Point, AnchorProperties>[] = []; anchors: GeoJSON.Feature<GeoJSON.Point, AnchorProperties>[] = [];
popup: Popup; popup: maplibregl.Popup;
popupElement: HTMLElement; popupElement: HTMLElement;
fileUnsubscribe: () => void = () => {}; fileUnsubscribe: () => void = () => {};
unsubscribes: Function[] = []; unsubscribes: Function[] = [];
@@ -63,7 +61,7 @@ export class RoutingControls {
draggedAnchorIndex: number | null = null; draggedAnchorIndex: number | null = null;
lastDraggedAnchorEventTime: number = 0; lastDraggedAnchorEventTime: number = 0;
draggingStartingPosition: Point = new Point(0, 0); draggingStartingPosition: maplibregl.Point = new maplibregl.Point(0, 0);
onMouseEnterBinded: () => void = this.onMouseEnter.bind(this); onMouseEnterBinded: () => void = this.onMouseEnter.bind(this);
onMouseLeaveBinded: () => void = this.onMouseLeave.bind(this); onMouseLeaveBinded: () => void = this.onMouseLeave.bind(this);
onClickBinded: (e: MapLayerMouseEvent) => void = this.onClick.bind(this); onClickBinded: (e: MapLayerMouseEvent) => void = this.onClick.bind(this);
@@ -82,7 +80,7 @@ export class RoutingControls {
constructor( constructor(
fileId: string, fileId: string,
file: Readable<GPXFileWithStatistics | undefined>, file: Readable<GPXFileWithStatistics | undefined>,
popup: Popup, popup: maplibregl.Popup,
popupElement: HTMLElement popupElement: HTMLElement
) { ) {
this.fileId = fileId; this.fileId = fileId;
@@ -185,7 +183,7 @@ export class RoutingControls {
this.layers.forEach((layer, zoom) => { this.layers.forEach((layer, zoom) => {
try { try {
let source = map_.getSource(layer.id) as GeoJSONSource | undefined; let source = map_.getSource(layer.id) as maplibregl.GeoJSONSource | undefined;
if (source) { if (source) {
source.setData({ source.setData({
type: 'FeatureCollection', type: 'FeatureCollection',
@@ -522,7 +520,7 @@ export class RoutingControls {
}); });
} }
async appendAnchor(e: MapMouseEvent) { async appendAnchor(e: maplibregl.MapMouseEvent) {
// Add a new anchor to the end of the last segment // Add a new anchor to the end of the last segment
if (get(streetViewEnabled) && get(streetViewSource) === 'google') { if (get(streetViewEnabled) && get(streetViewSource) === 'google') {
return; return;
@@ -611,7 +609,7 @@ export class RoutingControls {
await this.routeBetweenAnchors([lastAnchor, newAnchor], [lastAnchorPoint, newAnchorPoint]); await this.routeBetweenAnchors([lastAnchor, newAnchor], [lastAnchorPoint, newAnchorPoint]);
} }
addIntermediateAnchor(e: MapMouseEvent) { addIntermediateAnchor(e: maplibregl.MapMouseEvent) {
e.preventDefault(); e.preventDefault();
if (this.temporaryAnchor !== null) { if (this.temporaryAnchor !== null) {
@@ -8,13 +8,13 @@ import { get } from 'svelte/store';
import { fileStateCollection } from '$lib/logic/file-state'; import { fileStateCollection } from '$lib/logic/file-state';
import { fileActions } from '$lib/logic/file-actions'; import { fileActions } from '$lib/logic/file-actions';
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor'; import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
import type { Map, GeoJSONSource, MapLayerMouseEvent } from 'maplibre-gl'; import type { GeoJSONSource } from 'maplibre-gl';
import { ANCHOR_LAYER_KEY } from '$lib/components/map/style'; import { ANCHOR_LAYER_KEY } from '$lib/components/map/style';
import type { MapLayerEventManager } from '$lib/components/map/map-layer-event-manager'; import type { MapLayerEventManager } from '$lib/components/map/map-layer-event-manager';
import { loadSVGIcon } from '$lib/utils'; import { loadSVGIcon } from '$lib/utils';
export class SplitControls { export class SplitControls {
map: Map; map: maplibregl.Map;
layerEventManager: MapLayerEventManager; layerEventManager: MapLayerEventManager;
unsubscribes: Function[] = []; unsubscribes: Function[] = [];
@@ -22,7 +22,7 @@ export class SplitControls {
layerOnMouseLeaveBinded: () => void = this.layerOnMouseLeave.bind(this); layerOnMouseLeaveBinded: () => void = this.layerOnMouseLeave.bind(this);
layerOnClickBinded: (e: any) => void = this.layerOnClick.bind(this); layerOnClickBinded: (e: any) => void = this.layerOnClick.bind(this);
constructor(map: Map, layerEventManager: MapLayerEventManager) { constructor(map: maplibregl.Map, layerEventManager: MapLayerEventManager) {
this.map = map; this.map = map;
this.layerEventManager = layerEventManager; this.layerEventManager = layerEventManager;
loadSVGIcon( loadSVGIcon(
@@ -160,7 +160,7 @@ export class SplitControls {
mapCursor.notify(MapCursorState.SPLIT_CONTROL, false); mapCursor.notify(MapCursorState.SPLIT_CONTROL, false);
} }
layerOnClick(e: MapLayerMouseEvent) { layerOnClick(e: maplibregl.MapLayerMouseEvent) {
let coordinates = (e.features![0].geometry as GeoJSON.Point).coordinates; let coordinates = (e.features![0].geometry as GeoJSON.Point).coordinates;
fileActions.split( fileActions.split(
get(splitAs), get(splitAs),
@@ -16,7 +16,7 @@
import { fileActions } from '$lib/logic/file-actions'; import { fileActions } from '$lib/logic/file-actions';
import { map } from '$lib/components/map/map'; import { map } from '$lib/components/map/map';
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor'; import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
import { Marker } from 'maplibre-gl'; import maplibregl from 'maplibre-gl';
import { getSvgForSymbol } from '$lib/components/map/gpx-layer/gpx-layer'; import { getSvgForSymbol } from '$lib/components/map/gpx-layer/gpx-layer';
let props: { let props: {
@@ -41,7 +41,7 @@
}) })
); );
let marker: Marker | null = null; let marker: maplibregl.Marker | null = null;
function reset() { function reset() {
if ($selectedWaypoint) { if ($selectedWaypoint) {
@@ -125,7 +125,7 @@
let element = document.createElement('div'); let element = document.createElement('div');
element.classList.add('w-8', 'h-8'); element.classList.add('w-8', 'h-8');
element.innerHTML = getSvgForSymbol(symbolKey); element.innerHTML = getSvgForSymbol(symbolKey);
marker = new Marker({ marker = new maplibregl.Marker({
element, element,
anchor: 'bottom', anchor: 'bottom',
}) })
+2 -2
View File
@@ -50,5 +50,5 @@ Um die Ausrichtung und Neigung der Karte zu steuern, können Sie die Karte auch
### <Maximize2 size="16" class="inline-block" style="margin-bottom: 2px" /> Full screen ### <Maximize2 size="16" class="inline-block" style="margin-bottom: 2px" /> Full screen
Vollbildmodus ein- oder ausschalten. Enter or exit full screen mode.
Du kannst auch <kbd>F11</kbd> drücken, um zu wechseln, oder <kbd>Escape</kbd> zum Beenden. You can also press <kbd>F11</kbd> to toggle, or <kbd>Escape</kbd> to exit.
-8
View File
@@ -1,5 +1,3 @@
import { writable } from 'svelte/store';
type Dictionary = { type Dictionary = {
[key: string]: string | Dictionary; [key: string]: string | Dictionary;
}; };
@@ -12,7 +10,6 @@ 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);
@@ -41,7 +38,6 @@ 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;
} }
@@ -71,10 +67,6 @@ 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();
-1
View File
@@ -10,6 +10,5 @@ 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: '简体中文',
}; };
+4 -4
View File
@@ -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 { LngLatBounds } from 'maplibre-gl'; import maplibregl 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: LngLatBounds = new LngLatBounds(); private _bounds: maplibregl.LngLatBounds = new maplibregl.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)[] = [];
@@ -87,12 +87,12 @@ export class BoundsManager {
} }
this._unsubscribes.forEach((unsubscribe) => unsubscribe()); this._unsubscribes.forEach((unsubscribe) => unsubscribe());
this._unsubscribes = []; this._unsubscribes = [];
this._bounds = new LngLatBounds([180, 90, -180, -90]); this._bounds = new maplibregl.LngLatBounds([180, 90, -180, -90]);
} }
centerMapOnSelection() { centerMapOnSelection() {
let selected = get(selection).getSelected(); let selected = get(selection).getSelected();
let bounds = new LngLatBounds(); let bounds = new maplibregl.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) => {
+6 -6
View File
@@ -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 { LngLatBounds } from 'maplibre-gl'; import maplibregl from 'maplibre-gl';
export class GPXStatisticsTree { export class GPXStatisticsTree {
level: ListLevel; level: ListLevel;
statistics: { statistics: {
[key: string]: GPXStatisticsTree | GPXStatistics; [key: string]: GPXStatisticsTree | GPXStatistics;
} = {}; } = {};
wptBounds: LngLatBounds; wptBounds: maplibregl.LngLatBounds;
constructor(element: GPXFile | Track) { constructor(element: GPXFile | Track) {
this.wptBounds = new LngLatBounds(); this.wptBounds = new maplibregl.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: LngLatBounds): boolean { intersectsBBox(bounds: maplibregl.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 LngLatBounds( const bbox = new maplibregl.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: LngLatBounds): boolean { intersectsWaypointBBox(bounds: maplibregl.LngLatBounds): boolean {
return !this.wptBounds.isEmpty() && this.wptBounds.intersects(bounds); return !this.wptBounds.isEmpty() && this.wptBounds.intersects(bounds);
} }
} }
+4 -4
View File
@@ -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 { Map as MapLibreMap, LngLatBounds } from 'maplibre-gl'; import maplibregl 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 LngLatBounds(southWest, northEast); let bounds = new maplibregl.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 LngLatBounds(); let bbox = new maplibregl.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: MapLibreMap, id: string, svg: string, size: number = 100) { export function loadSVGIcon(map: maplibregl.Map, 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 = () => {
+3 -3
View File
@@ -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": "Vollbildmodus", "fullscreen": "Full screen",
"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": "Das Anfordern von Höhendaten löscht die vorhandenen Höhendaten, falls vorhanden, und ersetzt diese durch Daten von Mapterhorn.", "help": "Requesting elevation data will erase the existing elevation data, if any, and replace it with data from 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 Satellit", "libertySatellite": "Liberty Satellite",
"osm": "OpenMapTiles OSM", "osm": "OpenMapTiles OSM",
"osmTopo": "OpenMapTiles OSM Topo", "osmTopo": "OpenMapTiles OSM Topo",
"esriSatellite": "Esri Satellite", "esriSatellite": "Esri Satellite",
+18 -18
View File
@@ -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": "Pantaila osoa", "fullscreen": "Full screen",
"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": "Eskuin klik eta errestan eraman", "right_click_drag": "Right-click drag",
"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": "Bukaera-puntua hasiera-puntutik urrutiegi dago", "distance": "The end point is too far from the start point",
"connection": "Ez da konexiorik topatu puntuen artean", "connection": "No connection found between the points",
"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": "Kota-datuak eskatzeak lehendik dauden kota-datuak ezabatuko ditu, halakorik balego, eta Mapterhorn-eko datuekin ordezkatuko dira.", "help": "Requesting elevation data will erase the existing elevation data, if any, and replace it with data from Mapterhorn.",
"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 edo MapLibre estiloko JSON", "url_placeholder": "WMTS, WMS or MapLibre style 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 Satelitea", "libertySatellite": "Liberty Satellite",
"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": "Funtzioak", "features": "Features",
"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": "Filosofia", "philosophy": "Philosophy",
"foss": "Doakoa, propagandarik gabe eta kode irekikoa", "foss": "Free, ad-free and open source",
"foss_description": "Webgunea doakoa da, iragarkirik gabe, eta iturburu-kodea publikoki eskuragarri dago GitHub-en.", "foss_description": "The website is free to use, without ads, and the source code is publicly available on GitHub.",
"privacy": "Pribatutasuna zaintzen du", "privacy": "Privacy-friendly",
"privacy_description": "Zure GPX fitxategiak ez dira inoiz zure nabigatzailetik irteten. Ez dago jarraipenik, ez datu-bilketarik.", "privacy_description": "Your GPX files never leave your browser. No tracking, no data collection.",
"community": "Komunitateak posible egin du", "community": "Made possible by the community",
"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.", "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.",
"support_button": "Lagundu gpx.studio Open Collectiveren bidez", "support_button": "Support gpx.studio on Open Collective",
"translate_button": "Lagundu webgunea itzultzen Crowdin-en" "translate_button": "Help translate the website on Crowdin"
}, },
"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 gakoa (aukeran, bakarrik behar da MapTiler mapetan)", "maptiler_key": "MapTiler key (optional, only required for MapTiler maps)",
"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",