@trailstash/ultra
Version:
A web based tool for making MapLibre GL maps with data from sources such as Overpass, GeoJSON, GPX, KML, TCX, etc
106 lines (102 loc) • 2.57 kB
JavaScript
import { fetchIfHTTP } from "./util.js";
import { gpx } from "@tmcw/togeojson";
const layers = (source) => [
{
id: "ultra-gpx-line-casing",
type: "line",
source: "ultra",
layout: {
"line-cap": "round",
"line-join": "round",
},
paint: {
"line-color": "rgb(164, 112, 179)",
"line-opacity": 0.8,
"line-width": 2,
"line-gap-width": 5,
},
},
{
id: "ultra-gpx-line",
type: "line",
source: "ultra",
layout: {
"line-cap": "round",
"line-join": "round",
},
paint: {
"line-color": "rgb(226, 126, 255)",
"line-opacity": 0.5,
"line-width": 5,
},
},
{
id: `${source}-gpx-dir`,
type: "symbol",
source,
filter: ["==", ["geometry-type"], "LineString"],
layout: {
"symbol-placement": "line",
"symbol-spacing": 50,
"icon-image": "maki:triangle",
"icon-rotate": 90,
"icon-size": 0.3,
},
paint: {
"icon-color": "rgb(164, 112, 179)",
"icon-halo-color": "rgb(226, 126, 255)",
"icon-halo-width": 1,
},
},
{
id: `${source}-gpx-poi`,
type: "symbol",
source,
filter: ["==", ["geometry-type"], "Point"],
layout: {
"icon-anchor": "bottom",
"icon-image": "maki:marker",
"icon-overlap": "always",
"text-field": ["get", "name"],
"text-variable-anchor": ["bottom-left", "bottom-right"],
"text-justify": "auto",
"text-radial-offset": 1,
},
paint: {
"icon-color": "rgba(255, 255, 51, 1)",
"icon-halo-color": "rgba(51, 51, 51, 0.8)",
"icon-halo-width": 1,
"icon-halo-blur": 2,
"text-color": "#333",
"text-halo-color": "rgba(255,255,255,0.8)",
"text-halo-width": 1.5,
},
},
];
const detect = async (query) => {
query = await fetchIfHTTP(query);
const doc = new window.DOMParser().parseFromString(query, "text/xml");
if (
!doc.querySelector("parsererror") &&
Array.from(doc.childNodes).some((x) => x.nodeName === "gpx")
) {
return true;
}
};
export default {
source: async function (query, controller) {
let doc = new window.DOMParser().parseFromString(query, "text/xml");
if (doc.querySelector("parsererror")) {
const resp = await fetch(query.trim(), { signal: controller.signal });
doc = new window.DOMParser().parseFromString(
await resp.text(),
"text/xml",
);
}
const data = gpx(doc);
return { type: "geojson", data, generateId: true };
},
layers,
detect,
fitBounds: true,
};