You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
3.0 KiB
TypeScript
93 lines
3.0 KiB
TypeScript
import { Control, ControlPosition, Layer } from 'leaflet';
|
|
import { defineProps, str } from '../core/props.ts';
|
|
import { WithProps, registerWithParent } from '../core/utils.ts';
|
|
import { LeafletRegisterEvent } from '../core/register.ts';
|
|
|
|
const PROPS = defineProps({
|
|
position: str('topright'),
|
|
});
|
|
|
|
export class LeafletControlLayers extends WithProps(HTMLElement, PROPS) {
|
|
#obj?: Control.Layers;
|
|
|
|
connectedCallback() {
|
|
const baseLayers: Record<string, Layer> = {};
|
|
const overlays: Record<string, Layer> = {};
|
|
const uncheckedLayers: Layer[] = [];
|
|
|
|
for (const child of this.querySelectorAll(':scope > *')) {
|
|
const layer = (child as unknown as { leafletObject?: Layer }).leafletObject;
|
|
const name = child.getAttribute('name');
|
|
if (!name || !layer) continue;
|
|
const base = child.getAttribute('type') === 'base';
|
|
const checked = child.hasAttribute('checked');
|
|
(base ? baseLayers : overlays)[name] = layer;
|
|
if (!checked) uncheckedLayers.push(layer);
|
|
}
|
|
|
|
const map = this.#map;
|
|
for (const layer of uncheckedLayers) map?.removeLayer(layer);
|
|
|
|
this.#obj = new Control.Layers(baseLayers, overlays, {
|
|
position: this.getAttribute('position') as ControlPosition | undefined,
|
|
collapsed: !this.hasAttribute('collapsed') || this.getAttribute('collapsed') !== 'false',
|
|
autoZIndex:
|
|
!this.hasAttribute('auto-z-index') || this.getAttribute('auto-z-index') !== 'false',
|
|
hideSingleBase: this.hasAttribute('hide-single-base'),
|
|
sortLayers: this.hasAttribute('sort-layers'),
|
|
});
|
|
|
|
registerWithParent(this, this.#obj);
|
|
this.addEventListener('leaflet-register', this.#onChildRegister);
|
|
}
|
|
|
|
disconnectedCallback() {
|
|
this.removeEventListener('leaflet-register', this.#onChildRegister);
|
|
this.#obj?.remove();
|
|
this.#obj = undefined;
|
|
}
|
|
|
|
attributeChangedCallback(name: string) {
|
|
if (name === 'position' && this.#obj) {
|
|
this.#obj.setPosition(this.getAttribute('position') as ControlPosition);
|
|
}
|
|
}
|
|
|
|
get leafletObject() {
|
|
return this.#obj;
|
|
}
|
|
|
|
get #map():
|
|
| {
|
|
removeLayer(l: Layer): unknown;
|
|
addLayer(l: Layer): unknown;
|
|
}
|
|
| undefined {
|
|
const mapEl = this.closest('leaflet-map');
|
|
if (!mapEl) return undefined;
|
|
return (
|
|
mapEl as unknown as {
|
|
leafletObject?: {
|
|
removeLayer(l: Layer): unknown;
|
|
addLayer(l: Layer): unknown;
|
|
};
|
|
}
|
|
).leafletObject;
|
|
}
|
|
|
|
#onChildRegister = (e: LeafletRegisterEvent) => {
|
|
e.stopPropagation();
|
|
const el = e.detail.element;
|
|
const layer = e.detail.leafletObject;
|
|
const name = el.getAttribute('name');
|
|
if (!name || !layer) return;
|
|
const base = el.getAttribute('type') === 'base';
|
|
const checked = el.hasAttribute('checked');
|
|
if (base) this.#obj!.addBaseLayer(layer, name);
|
|
else this.#obj!.addOverlay(layer, name);
|
|
if (checked) this.#map?.addLayer(layer);
|
|
};
|
|
}
|
|
|
|
customElements.define('leaflet-control-layers', LeafletControlLayers);
|