/** * Globe dragging: a drag on an orthographic spins the sphere. * * Panning a globe is the wrong gesture. It slides a picture of the earth around * inside its box, leaves the far hemisphere permanently unreachable, and offers * the reader nothing they could not get by scrolling the page. Rotation is the * gesture the shape promises, so on a globe the drag belongs here rather than to * `ZoomPan`. * * The rotation is **versor-based** (see `geo/Versor`): the point the reader * grabbed stays under the cursor for the whole drag, at any latitude, however * far the globe has already turned. Accumulating Euler angles instead is the * cheap version, and it reads as cheap: near the poles a horizontal drag whips * the sphere around, because a degree of longitude there is worth almost no * surface. * * Two details that a naive implementation gets wrong and this one does not: * * - **Dragging off the disc keeps working.** Outside the globe's edge there is no * point to grab, so versor has nothing to solve for. Rather than freeze, the * drag falls back to angular stepping, which is what the reader expects when * they fling the cursor past the limb. * - **Longitude wraps.** The spin runs through 360 degrees and out the other * side, so nothing stops at the antimeridian. * * @module interaction/GlobeRotation */ import type { Viewport } from '../geo/Viewport'; import type { InteractionOptions, ScreenPoint } from '../types'; export declare class GlobeRotation { readonly viewport: Viewport; /** Reassigned by the host when `updateOptions` changes the interaction tree. */ options: InteractionOptions; readonly onChange: () => void; readonly onEnd: () => void; /** Rotation and orientation at the moment the drag started. */ private _r0; private _q0; /** The grabbed point on the unit sphere. Null when the drag began off the disc. */ private _v0; private _last; private _spin; private _raf; /** Whether this gesture actually turned anything, so a click stays a click. */ private _turned; constructor({ viewport, options, onChange, onEnd, }: { viewport: Viewport; options: InteractionOptions; /** Called after every applied rotation, so the host can redraw. */ onChange: () => void; /** Called once the globe comes to rest, after any glide. */ onEnd?: () => void; }); /** * Whether a drag should spin rather than pan. * * `'auto'` (the default) means "on a globe, yes", and defers to * `pan.enabled: false`, because a caller who turned dragging off meant it and * should not be handed a different drag gesture in its place. `true` forces * rotation on any projection that can rotate and invert, which is how a * stereographic or azimuthal view opts in. */ get enabled(): boolean; get spinning(): boolean; /** Grab the sphere at a screen point. */ start(point: ScreenPoint): void; /** Continue a drag. Returns false when there was nothing to rotate. */ move(point: ScreenPoint): boolean; /** Let go, gliding to a stop unless inertia is off. */ release(): void; /** Halt a glide in place. Called before any new gesture. */ stop(): void; /** The point on the unit sphere under a screen position, if there is one. */ private _grab; /** * Re-establish the grab after an angular step, so a drag can cross the limb in * either direction without a discontinuity. */ private _reanchor; /** The globe's on-screen radius in pixels, camera zoom included. */ private _radius; /** Apply a rotation and record what it was worth, for inertia. */ private _apply; } //# sourceMappingURL=GlobeRotation.d.ts.map