103 lines
2.2 KiB
TypeScript
103 lines
2.2 KiB
TypeScript
import { FolkElement } from '@lib';
|
|
import { css, unsafeCSS } from '@lit/reactive-element';
|
|
import { LatLng, LatLngExpression, LeafletEvent, map, tileLayer } from 'leaflet';
|
|
// @ts-ignore
|
|
// Vite specific import :(
|
|
import leafletCSS from 'leaflet/dist/leaflet.css?inline';
|
|
|
|
export class RecenterEvent extends Event {
|
|
constructor() {
|
|
super('recenter', { bubbles: true });
|
|
}
|
|
}
|
|
|
|
export class FolkMap extends FolkElement {
|
|
static override tagName = 'folk-map';
|
|
|
|
static override styles = css`
|
|
${unsafeCSS(leafletCSS)}
|
|
:host {
|
|
display: block;
|
|
}
|
|
|
|
:host > div {
|
|
height: 100%;
|
|
width: 100%;
|
|
}
|
|
`;
|
|
|
|
#container = document.createElement('div');
|
|
#map = map(this.#container);
|
|
|
|
override createRenderRoot() {
|
|
const root = super.createRenderRoot();
|
|
|
|
root.appendChild(this.#container);
|
|
|
|
this.#map.addLayer(
|
|
tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
maxZoom: 19,
|
|
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
|
|
}),
|
|
);
|
|
|
|
this.#map.setView(
|
|
(this.getAttribute('coordinates') || '0, 0').split(',').map(Number) as LatLngExpression,
|
|
Number(this.getAttribute('zoom') || 13),
|
|
);
|
|
|
|
return root;
|
|
}
|
|
|
|
connectedCallback(): void {
|
|
super.connectedCallback();
|
|
|
|
// Move end includes changes to zoom
|
|
this.#map.on('moveend', this.handleEvent);
|
|
}
|
|
|
|
disconnectedCallback(): void {
|
|
super.disconnectedCallback();
|
|
|
|
// Move end includes changes to zoom
|
|
this.#map.off('moveend', this.handleEvent);
|
|
}
|
|
|
|
get lat() {
|
|
return this.coordinates.lat;
|
|
}
|
|
set lat(lat) {
|
|
this.coordinates = [lat, this.lng];
|
|
}
|
|
|
|
get lng() {
|
|
return this.coordinates.lng;
|
|
}
|
|
set lng(lng) {
|
|
this.coordinates = [this.lat, lng];
|
|
}
|
|
|
|
get coordinates(): LatLng {
|
|
return this.#map.getCenter();
|
|
}
|
|
set coordinates(coordinates: LatLngExpression) {
|
|
this.#map.setView(coordinates);
|
|
}
|
|
|
|
get zoom() {
|
|
return this.#map.getZoom();
|
|
}
|
|
set zoom(zoom) {
|
|
this.#map.setZoom(zoom);
|
|
}
|
|
|
|
handleEvent = (event: LeafletEvent) => {
|
|
switch (event.type) {
|
|
case 'moveend': {
|
|
this.dispatchEvent(new RecenterEvent());
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
}
|