import { Deck, Viewport, WebMercatorViewport, Widget, WidgetPlacement, } from '@deck.gl/core'; import {render} from 'preact'; export type ScaleWidgetProps = { id?: string; placement?: WidgetPlacement; viewId?: string | null; maxWidth?: number; useImperial?: boolean; } export default class ScaleWidget extends Widget { id = 'scale'; placement: WidgetPlacement = 'bottom-left'; viewId?: string | null = null; viewport?: Viewport; className: string = "ecoscope-scale-widget"; constructor(props: ScaleWidgetProps) { super(props); this.setProps(props); } setProps(props: Partial) { props.maxWidth = props.maxWidth ?? 300; props.useImperial = props.useImperial ?? false; super.setProps(props); } onViewportChange(viewport: Viewport) { this.viewport = viewport; this.updateHTML(); } onRenderHTML(rootElement: HTMLElement): void { if (this.viewport instanceof WebMercatorViewport) { const meters = this.viewport.metersPerPixel * this.props.maxWidth; let distance: number let label: string; if (this.props.useImperial) { const feet = meters * 3.2808399; if (feet > 5280) { distance = feet / 5280; label = 'mi'; } else { distance = feet; label = 'ft'; } } else { distance = meters < 1000 ? meters : meters / 1000; label = meters < 1000 ? 'm' : 'km'; } const ratio = this.roundNumber(distance) / distance; distance = this.roundNumber(distance); const width = `${Math.round(this.props.maxWidth * ratio * (4 / 3))}px`; const ui = (
0 {distance / 2} {distance} {label}
); render(ui, rootElement); } } roundNumber(number: number) { const pow10 = Math.pow(10, `${Math.floor(number)}`.length - 1); let d = number / pow10; d = d >= 10 ? 10 : d >= 5 ? 5 : d >= 3 ? 3 : d >= 2 ? 2 : 1; return pow10 * d; } }