import { _GlobeViewport, Viewport, WebMercatorViewport, Widget, WidgetPlacement, } from '@deck.gl/core'; import {render} from 'preact'; export type NorthArrowWidgetProps = { id?: string; placement?: WidgetPlacement; viewId?: string | null; style?: Partial; }; export default class NorthArrowWidget extends Widget { id = 'na-widget'; placement: WidgetPlacement = 'top-left'; viewports: {[id: string]: Viewport} = {}; className: string = "ecoscope-north-arrow-widget"; constructor(props: NorthArrowWidgetProps) { super(props); this.setProps(props); } onAdd({deck}) { const element = document.createElement('div'); element.classList.add('deck-widget', this.className); Object.entries(this.props.style).map(([key, value]) => { element.style.setProperty(key, value as string); }); this.deck = deck; this.updateHTML(); return element; } setProps(props: Partial) { this.placement = props.placement ?? this.placement; this.viewId = props.viewId ?? this.viewId; super.setProps(props); } onRedraw() { this.updateHTML(); } onViewportChange(viewport: Viewport) { // no need to update if viewport is the same if (!viewport.equals(this.viewports[viewport.id])) { this.viewports[viewport.id] = viewport; this.updateHTML(); } } onRenderHTML(rootElement: HTMLElement): void { const viewId = this.viewId || Object.values(this.viewports)[0]?.id || 'default-view'; const viewport = this.viewports[viewId]; const [rz, rx] = this.getRotation(viewport); const ui = (
); render(ui, rootElement); } getRotation(viewport?: Viewport) { if (viewport instanceof WebMercatorViewport) { return [-viewport.bearing, viewport.pitch]; } else if (viewport instanceof _GlobeViewport) { return [0, Math.max(-80, Math.min(80, viewport.latitude))]; } return [0, 0]; } }