User interaction controllers for handling navigation and manipulation events across different view types, providing intuitive control schemes for various visualization scenarios.
Abstract base class for user interaction controllers that handle input events and update view states.
/**
* Abstract base class for user interaction controllers
* Handles input events and translates them to view state changes
*/
abstract class Controller {
/** Initialize controller with properties */
constructor(props: ControllerProps);
/** Process user input event */
handleEvent(event: MjolnirEvent): boolean;
/** Update controller properties */
setProps(props: ControllerProps): void;
/** Update viewport reference */
updateViewport(viewport: Viewport): void;
/** Get current interaction state */
getState(): InteractionState;
/** Set interaction state */
setState(state: Partial<InteractionState>): void;
/** Controller configuration */
readonly props: ControllerProps;
}
interface ControllerProps {
/** Function to create viewport from view state */
makeViewport: (viewState: any) => Viewport;
/** View state change callback */
onViewStateChange?: (params: ViewStateChangeParameters) => void;
/** Interaction state change callback */
onStateChange?: (state: InteractionState) => void;
/** Event manager instance */
eventManager?: EventManager;
/** Enable scroll wheel zoom */
scrollZoom?: boolean;
/** Enable mouse/touch drag to pan */
dragPan?: boolean;
/** Enable drag to rotate */
dragRotate?: boolean;
/** Enable double-click to zoom */
doubleClickZoom?: boolean;
/** Enable touch gestures for zoom */
touchZoom?: boolean;
/** Enable touch gestures for rotation */
touchRotate?: boolean;
/** Enable keyboard navigation */
keyboard?: boolean;
/** Inertia settings */
inertia?: number | boolean;
/** Zoom speed multiplier */
scrollZoomSpeed?: number;
/** Pan speed multiplier */
dragPanSpeed?: number;
/** Rotation speed multiplier */
dragRotateSpeed?: number;
/** Double-click zoom speed */
doubleClickZoomSpeed?: number;
/** Touch zoom speed */
touchZoomSpeed?: number;
/** Touch rotation speed */
touchRotateSpeed?: number;
/** Keyboard movement speed */
keyboardSpeed?: number;
}
interface InteractionState {
/** Whether currently dragging */
isDragging: boolean;
/** Whether currently panning */
isPanning: boolean;
/** Whether currently rotating */
isRotating: boolean;
/** Whether currently zooming */
isZooming: boolean;
/** Whether mouse/touch is pressed */
isPressed: boolean;
/** Current pointer position */
startPointerPosition?: [number, number];
/** Pointer position when interaction started */
pointerPosition?: [number, number];
}
interface ViewStateChangeParameters {
/** New view state */
viewState: any;
/** Previous view state */
oldViewState?: any;
/** View state change triggered by user interaction */
interactionState?: InteractionState;
/** ID of the view that changed */
viewId?: string;
}Usage Examples:
import { MapController } from "@deck.gl/core";
// Custom controller configuration
const controller = new MapController({
makeViewport: (viewState) => new WebMercatorViewport(viewState),
scrollZoom: true,
dragPan: true,
dragRotate: true,
doubleClickZoom: true,
touchZoom: true,
touchRotate: true,
keyboard: true,
scrollZoomSpeed: 0.5,
onViewStateChange: ({viewState}) => {
console.log('View state changed:', viewState);
},
onStateChange: (state) => {
console.log('Interaction state:', state);
}
});Controller for map-style interactions supporting pan, zoom, rotate, and tilt operations commonly used in geospatial applications.
/**
* Map controller for geospatial applications
* Provides standard map interaction patterns (pan, zoom, rotate, pitch)
*/
class MapController extends Controller {
/** Initialize map controller */
constructor(props: MapControllerProps);
/** Handle map-specific events */
handleEvent(event: MjolnirEvent): boolean;
}
interface MapControllerProps extends ControllerProps {
/** Maximum pitch angle in degrees */
maxPitch?: number;
/** Minimum pitch angle in degrees */
minPitch?: number;
/** Maximum zoom level */
maxZoom?: number;
/** Minimum zoom level */
minZoom?: number;
/** Enable pitch (tilt) interactions */
touchPitch?: boolean;
/** Linear transition interpolator */
transitionInterpolator?: TransitionInterpolator;
/** Transition duration in milliseconds */
transitionDuration?: number;
/** Transition easing function */
transitionEasing?: (t: number) => number;
/** Called when transition starts */
onTransitionStart?: () => void;
/** Called during transition */
onTransitionUpdate?: (viewState: any) => void;
/** Called when transition ends */
onTransitionEnd?: () => void;
}Usage Examples:
import { Deck, MapView, MapController, FlyToInterpolator } from "@deck.gl/core";
// Map with custom controller settings
const deck = new Deck({
views: [new MapView({id: 'map'})],
controller: {
type: MapController,
scrollZoom: true,
dragPan: true,
dragRotate: true,
doubleClickZoom: true,
touchZoom: true,
touchRotate: true,
touchPitch: true,
keyboard: true,
inertia: true,
maxZoom: 20,
minZoom: 0,
maxPitch: 85,
minPitch: 0,
scrollZoomSpeed: 0.5,
dragPanSpeed: 1.0,
dragRotateSpeed: 1.0
},
initialViewState: {
longitude: -122.4,
latitude: 37.8,
zoom: 12
}
});
// Programmatic transition
deck.setProps({
viewState: {
longitude: -74.006,
latitude: 40.7128,
zoom: 14,
pitch: 45,
bearing: 30,
transitionDuration: 3000,
transitionInterpolator: new FlyToInterpolator()
}
});Controller for first-person navigation with WASD keyboard controls and mouse look functionality.
/**
* First-person controller for immersive 3D navigation
* WASD movement with mouse look controls
*/
class FirstPersonController extends Controller {
/** Initialize first-person controller */
constructor(props: FirstPersonControllerProps);
/** Handle first-person specific events */
handleEvent(event: MjolnirEvent): boolean;
}
interface FirstPersonControllerProps extends ControllerProps {
/** Movement speed for keyboard navigation */
movementSpeed?: number;
/** Mouse sensitivity for look controls */
mouseSensitivity?: number;
/** Maximum pitch angle (look up/down limit) */
maxPitch?: number;
/** Minimum pitch angle */
minPitch?: number;
/** Enable mouse pointer lock */
pointerLock?: boolean;
}Usage Examples:
import { Deck, FirstPersonView, FirstPersonController } from "@deck.gl/core";
// First-person setup
const deck = new Deck({
views: [new FirstPersonView({id: 'fps'})],
controller: {
type: FirstPersonController,
keyboard: true,
movementSpeed: 100,
mouseSensitivity: 0.1,
maxPitch: 89,
minPitch: -89,
pointerLock: true
},
initialViewState: {
position: [0, 0, 100],
bearing: 0,
pitch: 0
}
});Controller for orbital/trackball-style 3D navigation around a target point.
/**
* Orbit controller for 3D trackball navigation
* Rotates camera around a fixed target point
*/
class OrbitController extends Controller {
/** Initialize orbit controller */
constructor(props: OrbitControllerProps);
/** Handle orbit-specific events */
handleEvent(event: MjolnirEvent): boolean;
}
interface OrbitControllerProps extends ControllerProps {
/** Rotation speed multiplier */
rotationSpeed?: number;
/** Zoom speed multiplier */
zoomSpeed?: number;
/** Pan speed multiplier */
panSpeed?: number;
/** Maximum zoom level */
maxZoom?: number;
/** Minimum zoom level */
minZoom?: number;
/** Enable auto-rotation */
autoRotate?: boolean;
/** Auto-rotation speed */
autoRotateSpeed?: number;
/** Enable damping/inertia */
enableDamping?: boolean;
/** Damping factor */
dampingFactor?: number;
}Usage Examples:
import { Deck, OrbitView, OrbitController } from "@deck.gl/core";
// 3D orbit setup
const deck = new Deck({
views: [new OrbitView({id: 'orbit'})],
controller: {
type: OrbitController,
rotationSpeed: 1.0,
zoomSpeed: 0.5,
panSpeed: 1.0,
maxZoom: 10,
minZoom: -5,
enableDamping: true,
dampingFactor: 0.1
},
initialViewState: {
target: [0, 0, 0],
rotationX: 30,
rotationOrbit: 45,
zoom: 0,
orbitAxis: 'Y'
}
});Controller for orthographic view interactions with 2D-style pan and zoom.
/**
* Orthographic controller for 2D/technical drawing interactions
* Pan and zoom without perspective distortion
*/
class OrthographicController extends Controller {
/** Initialize orthographic controller */
constructor(props: OrthographicControllerProps);
/** Handle orthographic-specific events */
handleEvent(event: MjolnirEvent): boolean;
}
interface OrthographicControllerProps extends ControllerProps {
/** Maximum zoom level */
maxZoom?: number;
/** Minimum zoom level */
minZoom?: number;
/** Zoom speed multiplier */
zoomSpeed?: number;
/** Pan speed multiplier */
panSpeed?: number;
/** Enable zoom to cursor position */
zoomToCursor?: boolean;
}Experimental controller for 3D globe navigation.
/**
* Experimental globe controller for 3D earth navigation
* Specialized interactions for globe visualization
*/
class _GlobeController extends Controller {
/** Initialize globe controller */
constructor(props: GlobeControllerProps);
/** Handle globe-specific events */
handleEvent(event: MjolnirEvent): boolean;
}
interface GlobeControllerProps extends ControllerProps {
/** Globe rotation speed */
globeRotationSpeed?: number;
/** Maximum zoom into globe surface */
maxZoom?: number;
/** Minimum zoom (how far to pull back) */
minZoom?: number;
}Comprehensive event handling system for user interactions.
// Event constants
const TRANSITION_EVENTS: {
readonly BREAK: "transitionBreak";
readonly SNAP_TO_END: "transitionSnapToEnd";
readonly UPDATE: "transitionUpdate";
readonly END: "transitionEnd";
};
// Mjolnir.js event types (re-exported from mjolnir.js)
interface MjolnirEvent {
type: string;
srcEvent: Event;
target: any;
stopPropagation(): void;
preventDefault(): void;
stopImmediatePropagation(): void;
}
interface MjolnirPointerEvent extends MjolnirEvent {
offsetCenter: {x: number; y: number};
pointerType: string;
}
interface MjolnirGestureEvent extends MjolnirEvent {
scale?: number;
rotation?: number;
deltaX?: number;
deltaY?: number;
velocityX?: number;
velocityY?: number;
}
// Event handler configuration
interface RecognizerOptions {
/** Pan gesture recognizer options */
pan?: Omit<PanRecognizerOptions, 'event' | 'enable'>;
/** Pinch gesture recognizer options */
pinch?: Omit<PinchRecognizerOptions, 'event' | 'enable'>;
/** Multi-finger pan options */
multipan?: Omit<PanRecognizerOptions, 'event' | 'enable'>;
/** Double-click options */
dblclick?: Omit<TapRecognizerOptions, 'event' | 'enable'>;
/** Single click options */
click?: Omit<TapRecognizerOptions, 'event' | 'enable'>;
}Built-in transition system for smooth view state changes.
/**
* Transition manager handling smooth view state changes
* Automatically handles interpolation between states
*/
interface TransitionManager {
/** Process transition update */
processViewStateChange(params: ViewStateChangeParameters): any;
/** Get current transition state */
getViewportInTransition(): Viewport | null;
/** Break current transition */
breakTransition(): void;
}
// Transition interpolator types (referenced from transitions)
interface TransitionInterpolatorOptions {
/** Properties to interpolate */
transitionProps?: string[];
/** Interpolation curve */
curve?: number[];
/** Speed constant */
speed?: number;
}Usage Examples:
import {
Deck,
MapView,
MapController,
LinearInterpolator,
FlyToInterpolator
} from "@deck.gl/core";
// Advanced controller with transitions
const deck = new Deck({
views: [new MapView({id: 'map'})],
controller: {
inertia: 300,
scrollZoomSpeed: 0.01,
dragPanSpeed: 1.2,
dragRotateSpeed: 0.5,
doubleClickZoomSpeed: 2,
touchZoomSpeed: 0.5,
touchRotateSpeed: 0.3,
keyboard: {
zoomSpeed: 0.02,
moveSpeed: 0.1,
rotateSpeedX: 0.1,
rotateSpeedY: 0.1
}
},
initialViewState: {
longitude: -122.4,
latitude: 37.8,
zoom: 12,
pitch: 0,
bearing: 0
},
onViewStateChange: ({viewState, interactionState}) => {
if (interactionState?.isDragging) {
console.log('User is dragging');
}
return viewState;
}
});
// Smooth transition to new location
const flyToNewYork = () => {
deck.setProps({
viewState: {
longitude: -74.006,
latitude: 40.7128,
zoom: 14,
pitch: 45,
bearing: 30,
transitionDuration: 5000,
transitionInterpolator: new FlyToInterpolator({
speed: 2,
curve: 1.414
}),
onTransitionStart: () => console.log('Flying to New York...'),
onTransitionEnd: () => console.log('Arrived in New York!')
}
});
};
// Linear zoom transition
const zoomIn = () => {
deck.setProps({
viewState: {
...deck.props.viewState,
zoom: 16,
transitionDuration: 1000,
transitionInterpolator: new LinearInterpolator(['zoom'])
}
});
};