@trailstash/ultra
Version:
A web based tool for making MapLibre GL maps with data from sources such as Overpass, GeoJSON, GPX, KML, TCX, etc
104 lines (92 loc) • 2.72 kB
JavaScript
import * as maplibregl from "maplibre-gl";
import maplibreglStyle from "maplibre-gl/dist/maplibre-gl.css";
import { version as maplibreVersion } from "maplibre-gl/package.json";
import camelCase from "lodash.camelcase";
import kebabCase from "lodash.kebabcase";
const styleSheet = new CSSStyleSheet();
styleSheet.replaceSync(`
${maplibreglStyle}
:host, .map {
height: 100%;
width: 100%;
}
`);
const parseFloats = (value) => value.split(",").map(parseFloat);
const properties = {
mapStyle: { option: "style" },
zoom: { parseAttr: parseFloat },
center: { parseAttr: parseFloats },
pitch: { parseAttr: parseFloat },
bearing: { parseAttr: parseFloat },
maxBounds: { parseAttr: parseFloats },
bounds: { setter: "fitBounds", parseAttr: parseFloats },
};
class MapLibre extends HTMLElement {
static observedAttributes = Object.keys(properties).map(kebabCase);
options = {};
controls = [];
#properties = {};
constructor() {
super();
for (let [name, { option, setter, getter }] of Object.entries(properties)) {
if (option === undefined) {
option = name;
}
if (setter === undefined) {
setter = camelCase(`set-${option}`);
}
if (getter === undefined) {
getter = camelCase(`get-${option}`);
}
Object.defineProperty(this, name, {
get: function () {
if (this.map) {
return this.map[getter]();
}
return this.#properties[option];
},
set: function (value) {
if (this.map) {
this.map[setter](value);
}
this.#properties[option] = value;
},
});
}
}
attributeChangedCallback(name, oldValue, newValue) {
const option = camelCase(name);
if (properties[option]?.parseAttr) {
this[option] = properties[option].parseAttr(newValue);
} else {
this[option] = newValue;
}
}
async connectedCallback() {
const shadow = this.attachShadow({ mode: "open" });
shadow.adoptedStyleSheets.push(styleSheet);
const container = document.createElement("div");
container.classList.add("map");
shadow.appendChild(container);
this.map = new maplibregl.Map({
...this.options,
...this.#properties,
container,
});
for (const { type, options, position } of this.controls) {
let control = type;
if (
typeof type === "string" &&
type.endsWith("Control") &&
type in maplibregl
) {
control = new maplibregl[type](options);
}
if (control) {
this.map.addControl(control, position);
}
}
}
}
export { MapLibre, maplibregl, maplibreVersion };
export default MapLibre;