UNPKG

@trailstash/ultra

Version:

A web based tool for making MapLibre GL maps with data from sources such as Overpass, GeoJSON, GPX, KML, TCX, etc

124 lines (120 loc) 3.35 kB
import { fetchIfHTTP } from "./util.js"; import { kml } from "@tmcw/togeojson"; const layers = (source) => [ { id: `${source}-geojson-fill`, type: "fill", source, filter: ["==", ["geometry-type"], "Polygon"], paint: { "fill-color": ["coalesce", ["get", "fill"], "#555"], "fill-opacity": ["coalesce", ["get", "fill-opacity"], 0.3], }, }, { id: `${source}-geojson-fill-outline`, type: "line", source, filter: ["==", ["geometry-type"], "Polygon"], paint: { "line-color": ["coalesce", ["get", "stroke"], "#555"], "line-width": ["coalesce", ["get", "stroke-width"], 2], "line-opacity": ["coalesce", ["get", "stroke-opacity"], 1], }, layout: { "line-join": "round", "line-cap": "round", }, }, { id: `${source}-geojson-line-2`, type: "line", source, filter: ["==", ["geometry-type"], "LineString"], paint: { "line-color": ["coalesce", ["get", "stroke"], "#555"], "line-width": ["coalesce", ["get", "stroke-width"], 2], "line-opacity": ["coalesce", ["get", "stroke-opacity"], 1], }, layout: { "line-join": "round", "line-cap": "round", }, }, { id: `${source}-geojson-point`, type: "symbol", source, filter: ["==", ["geometry-type"], "Point"], layout: { "icon-overlap": "always", "icon-size": ["coalesce", ["get", "icon-scale"], 1], "icon-anchor": "bottom", "icon-image": "maki:marker", }, paint: { "icon-color": ["coalesce", ["get", "icon-color"], "#555"], "icon-halo-color": ["coalesce", ["get", "stroke-color"], "#fff"], "icon-halo-width": [ "coalesce", ["get", "stroke-width"], [ "case", ["==", ["get", "marker-size"], "large"], 3, ["==", ["get", "marker-size"], "medium"], 1.5, ["==", ["get", "marker-size"], "small"], 1, 1.5, ], ], }, }, ]; const detect = async (query) => { if (query.startsWith("https://www.google.com/maps/d/")) { return true; } query = await fetchIfHTTP(query); const doc = new window.DOMParser().parseFromString(query, "text/xml"); return ( !doc.querySelector("parsererror") && Array.from(doc.childNodes).some((x) => x.nodeName === "kml") ); }; export default { source: async function (query, controller) { if (query.startsWith("https://www.google.com/maps/d/")) { const url = new URL(query); const mid = url.searchParams.get("mid"); if (mid) { query = `https://www.google.com/maps/d/kml?mid=${mid}&forcekml=1`; } } 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 = kml(doc); return { type: "geojson", data, generateId: true }; }, layers, popupTemplate: ` <h2>{{properties.name}}</h2> <p>{{properties.description}}</p> <details> <summary>Properties</summary> {%- for prop in properties %} <code>{{ prop[0] }} = {{ prop[1] }}</code> <br> {%- endfor %} </details> `, detect, fitBounds: true, };