/** * Zoom, pan, pinch and box selection. * * Three details separate a map that feels right from one that feels cheap, and * all three are implemented here rather than left to the host app: * * - **Anchored zoom**: the geography under the pointer stays under the pointer. * - **Inertial pan**: releasing a drag decelerates instead of stopping dead. * - **A drag that ends on a feature is not a click on it.** Without that, panning * the map and releasing over a country selects the country, and box-selecting * over one drills into it. * * A drag means pan, and a drag with a modifier means "select what is in this box", * because a map has one drag gesture and panning has the stronger claim on it. * On a globe the drag is handed to `GlobeRotation` instead, which spins the * sphere; everything else here (the click slop, the pinch, the marquee) is * unchanged by that, because only the meaning of the movement differs. * * @module interaction/ZoomPan */ import type { Camera } from '../geo/Camera'; import type { GlobeRotation } from './GlobeRotation'; import type { InteractionOptions, ScreenPoint } from '../types'; /** A screen-space selection box, `[[x0, y0], [x1, y1]]`, already normalised. */ export type SelectBox = [ScreenPoint, ScreenPoint]; export type SelectBoxPhase = 'move' | 'end' | 'cancel'; export declare class ZoomPan { readonly container: HTMLElement; readonly camera: Camera; readonly options: InteractionOptions; readonly emit: (event: string, payload?: unknown) => void; readonly onSelectBox: (box: SelectBox | null, phase: SelectBoxPhase, additive: boolean) => void; /** Present on every map; it decides for itself whether this projection spins. */ readonly globe: GlobeRotation | null; /** Whether the drag in progress (or about to start) turns the globe. */ private _rotating; private _dragging; private _moved; private _last; private _velocity; private _inertiaRaf; private readonly _pointers; private _pinchDistance; private _marquee; /** * Set when a gesture travelled far enough to be a drag rather than a click. * * The browser still fires `click` after a drag that begins and ends on the same * element, so without this a pan that finishes over a country selects it. Cleared * by the next pointerdown, so a stale flag can never outlive one gesture, which a * timer-based version could. */ private _swallowClick; private readonly _onPointerDown; private readonly _onPointerMove; private readonly _onPointerUp; private readonly _onWheel; private readonly _onDblClick; constructor({ container, camera, options, emit, onSelectBox, globe, }: { container: HTMLElement; camera: Camera; options: InteractionOptions; emit?: (event: string, payload?: unknown) => void; /** Called as a selection box is dragged, and once when it is released. */ onSelectBox?: (box: SelectBox | null, phase: SelectBoxPhase, additive: boolean) => void; globe?: GlobeRotation | null; }); attach(): void; detach(): void; private _handlePointerDown; private _handlePointerMove; private _handlePointerUp; /** * Whether the click now arriving is the tail of a drag, consuming the flag. * * Consume-once rather than a time window: the flag is set on pointerup and * cleared either by the click that follows or by the next pointerdown, so it * cannot leak into an unrelated click however long the reader waits. */ shouldSwallowClick(): boolean; /** Abandon an in-progress selection box, e.g. on Escape. */ cancelSelectBox(): boolean; get selecting(): boolean; private _marqueeWanted; private _marqueeBox; private _boxSize; private _detachWindowListeners; private _handleWheel; private _handleDblClick; private _currentPinchDistance; private _pinchCentre; private _startInertia; private _stopInertia; } //# sourceMappingURL=ZoomPan.d.ts.map