UNPKG

maplair

Version:

JavaScript library for mobile-friendly interactive maps

235 lines (234 loc) • 6.73 kB
import { setOptions } from "../../core/Util.js"; import { Point } from "../../geometry/Point.js"; import { off, on } from "../../dom/DomEvent.js"; import { setPosition } from "../../dom/DomUtil.js"; import { LatLng } from "../../geo/LatLng.js"; import { Layer } from "../Layer.js"; import { DefaultIcon } from "./DefaultIcon.js"; import { MarkerDrag } from "./Marker.Drag.js"; //#region src/layer/marker/Marker.js var Marker = class Marker extends Layer { static { this.setDefaultOptions({ icon: new DefaultIcon(), interactive: true, keyboard: true, title: "", alt: "Marker", zIndexOffset: 0, opacity: 1, riseOnHover: false, riseOffset: 250, pane: "markerPane", shadowPane: "shadowPane", shadow: true, bubblingPointerEvents: false, autoPanOnFocus: true, draggable: false, autoPan: false, autoPanPadding: [50, 50], autoPanSpeed: 10 }); } constructor(latlng, options) { super(); setOptions(this, options); this._latlng = new LatLng(latlng); this.callInitHooks(Marker); } onAdd(map) { this._zoomAnimated = this._zoomAnimated && map.options.markerZoomAnimation; if (this._zoomAnimated) map.on("zoomanim", this._animateZoom, this); this._initIcon(); this.update(); if (map.options.markerCulling) this._updateCulling(); } onRemove(map) { if (this.dragging?.enabled()) { this.options.draggable = true; this.dragging.removeHooks(); } delete this.dragging; if (this._zoomAnimated) map.off("zoomanim", this._animateZoom, this); this._removeIcon(); this._removeShadow(); this._culled = false; } getEvents() { const events = { zoom: this.update, viewreset: this.update }; if (this._map?.options.markerCulling) events.moveend = this._updateCulling; return events; } getLatLng() { return this._latlng; } setLatLng(latlng) { const oldLatLng = this._latlng; this._latlng = new LatLng(latlng); if (this._map?.options.markerCulling) this._updateCulling(); this.update(); return this.fire("move", { oldLatLng, latlng: this._latlng }); } setZIndexOffset(offset) { this.options.zIndexOffset = offset; return this.update(); } getIcon() { return this.options.icon; } setIcon(icon) { this.options.icon = icon; if (this._map) { this._initIcon(); this.update(); } if (this._popup) this.bindPopup(this._popup, this._popup.options); return this; } getElement() { return this._icon; } update() { if (this._icon && this._map && !this._culled) { const pos = this._map.latLngToLayerPoint(this._latlng).round(); this._setPos(pos); } return this; } _initIcon() { const options = this.options, classToAdd = `maplair-zoom-${this._zoomAnimated ? "animated" : "hide"}`; const icon = options.icon.createIcon(this._icon); let addIcon = false; if (icon !== this._icon) { if (this._icon) this._removeIcon(); addIcon = true; if (options.title) icon.title = options.title; if (icon.tagName === "IMG") icon.alt = options.alt ?? ""; } icon.classList.add(classToAdd); if (options.keyboard) { icon.tabIndex = "0"; icon.setAttribute("role", "button"); } this._icon = icon; if (options.riseOnHover) this.on({ pointerover: this._bringToFront, pointerout: this._resetZIndex }); if (this.options.autoPanOnFocus) on(icon, "focus", this._panOnFocus, this); const newShadow = options.shadow ? options.icon.createShadow(this._shadow) : null; let addShadow = false; if (newShadow !== this._shadow) { this._removeShadow(); addShadow = true; } if (newShadow) { newShadow.classList.add(classToAdd); newShadow.alt = ""; } this._shadow = newShadow; if (options.opacity < 1) this._updateOpacity(); if (addIcon) this.getPane().appendChild(this._icon); this._initInteraction(); if (newShadow && addShadow) this.getPane(options.shadowPane).appendChild(this._shadow); } _removeIcon() { if (this.options.riseOnHover) this.off({ pointerover: this._bringToFront, pointerout: this._resetZIndex }); if (this.options.autoPanOnFocus) off(this._icon, "focus", this._panOnFocus, this); this._icon.remove(); this.removeInteractiveTarget(this._icon); this._icon = null; } _updateCulling() { if (!this._icon || !this._map) return; const visible = this._map.getBounds().pad(.5).contains(this._latlng) || !!this.dragging?._draggable?._moving || this._icon.contains(document.activeElement); if (visible === !this._culled) return; this._culled = !visible; if (visible) { this.getPane().appendChild(this._icon); if (this._shadow) this.getPane(this.options.shadowPane).appendChild(this._shadow); this.update(); } else { this._icon.remove(); this._shadow?.remove(); } } _removeShadow() { this._shadow?.remove(); this._shadow = null; } _setPos(pos) { if (this._icon) setPosition(this._icon, pos); if (this._shadow) setPosition(this._shadow, pos); this._zIndex = pos.y + this.options.zIndexOffset; this._resetZIndex(); } _updateZIndex(offset) { const zIndex = String(this._zIndex + offset); if (this._icon && this._icon.style.zIndex !== zIndex) this._icon.style.zIndex = zIndex; } _animateZoom(opt) { if (this._culled) return; const pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round(); this._setPos(pos); } _initInteraction() { if (!this.options.interactive) return; this._icon.classList.add("maplair-interactive"); this.addInteractiveTarget(this._icon); if (MarkerDrag) { let draggable = this.options.draggable; if (this.dragging) { draggable = this.dragging.enabled(); this.dragging.disable(); } this.dragging = new MarkerDrag(this); if (draggable) this.dragging.enable(); } } setOpacity(opacity) { this.options.opacity = opacity; if (this._map) this._updateOpacity(); return this; } _updateOpacity() { const opacity = this.options.opacity; if (this._icon) this._icon.style.opacity = opacity; if (this._shadow) this._shadow.style.opacity = opacity; } _bringToFront() { this._updateZIndex(this.options.riseOffset); } _resetZIndex() { this._updateZIndex(0); } _panOnFocus() { const map = this._map; if (!map) return; const iconOpts = this.options.icon.options; const size = iconOpts.iconSize ? new Point(iconOpts.iconSize) : new Point(0, 0); const anchor = iconOpts.iconAnchor ? new Point(iconOpts.iconAnchor) : new Point(0, 0); map.panInside(this._latlng, { paddingTopLeft: anchor, paddingBottomRight: size.subtract(anchor) }); } _getPopupAnchor() { return this.options.icon.options.popupAnchor; } _getTooltipAnchor() { return this.options.icon.options.tooltipAnchor; } }; //#endregion export { Marker }; //# sourceMappingURL=Marker.js.map