@trailstash/ultra
Version:
A web based tool for making MapLibre GL maps with data from sources such as Overpass, GeoJSON, GPX, KML, TCX, etc
100 lines (96 loc) • 2.28 kB
JavaScript
import { fetchIfHTTP } from "./util.js";
import { tcx } from "@tmcw/togeojson";
const layers = (source) => [
{
id: "ultra-tcx-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-tcx-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}-tcx-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}-tcx-poi`,
type: "symbol",
source,
filter: ["==", ["geometry-type"], "Point"],
layout: {
"icon-overlap": "always",
"icon-size": 0.5,
"icon-anchor": "bottom",
"icon-image": ["concat", "https://corsproxy.io/?", ["get", "icon"]],
},
},
*/
];
const detect = async (query) => {
query = await fetchIfHTTP(query);
const doc = new window.DOMParser().parseFromString(query, "text/xml");
if (
!doc.querySelector("parsererror") &&
doc.childNodes[0].nodeName === "TrainingCenterDatabase"
) {
return query;
}
};
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 = tcx(doc);
return { type: "geojson", data, generateId: true };
},
layers,
popupTemplate: `
<h2>{{properties.name}}</h2>
<p>{{properties.description}}</p>
`,
detect,
fitBounds: true,
};