React components for MapLibre GL JS and Mapbox GL JS that provide a React-friendly API wrapper for interactive mapping applications
—
Comprehensive event system and type definitions for react-map-gl, providing strongly-typed event handling for all map interactions, view state changes, and user interactions.
The event system provides comprehensive coverage of all map interactions with strongly-typed event objects.
/**
* Main event callback interface containing all possible map event handlers
*/
interface MapCallbacks {
// View state events
onMove?: (event: ViewStateChangeEvent) => void;
onMoveStart?: (event: ViewStateChangeEvent) => void;
onMoveEnd?: (event: ViewStateChangeEvent) => void;
onZoom?: (event: ViewStateChangeEvent) => void;
onZoomStart?: (event: ViewStateChangeEvent) => void;
onZoomEnd?: (event: ViewStateChangeEvent) => void;
onRotate?: (event: ViewStateChangeEvent) => void;
onRotateStart?: (event: ViewStateChangeEvent) => void;
onRotateEnd?: (event: ViewStateChangeEvent) => void;
onPitch?: (event: ViewStateChangeEvent) => void;
onPitchStart?: (event: ViewStateChangeEvent) => void;
onPitchEnd?: (event: ViewStateChangeEvent) => void;
// Mouse events
onClick?: (event: MapMouseEvent) => void;
onDblClick?: (event: MapMouseEvent) => void;
onMouseDown?: (event: MapMouseEvent) => void;
onMouseUp?: (event: MapMouseEvent) => void;
onMouseOver?: (event: MapMouseEvent) => void;
onMouseMove?: (event: MapMouseEvent) => void;
onMouseOut?: (event: MapMouseEvent) => void;
onContextMenu?: (event: MapMouseEvent) => void;
onMouseEnter?: (event: MapMouseEvent) => void;
onMouseLeave?: (event: MapMouseEvent) => void;
// Touch events
onTouchStart?: (event: MapTouchEvent) => void;
onTouchEnd?: (event: MapTouchEvent) => void;
onTouchMove?: (event: MapTouchEvent) => void;
onTouchCancel?: (event: MapTouchEvent) => void;
// Wheel events
onWheel?: (event: MapWheelEvent) => void;
// Drag events
onDragStart?: (event: ViewStateChangeEvent) => void;
onDrag?: (event: ViewStateChangeEvent) => void;
onDragEnd?: (event: ViewStateChangeEvent) => void;
// Box zoom events
onBoxZoomStart?: (event: MapBoxZoomEvent) => void;
onBoxZoomEnd?: (event: MapBoxZoomEvent) => void;
onBoxZoomCancel?: (event: MapBoxZoomEvent) => void;
// Map lifecycle events
onLoad?: (event: MapEvent) => void;
onResize?: (event: MapEvent) => void;
onRemove?: (event: MapEvent) => void;
onError?: (event: ErrorEvent) => void;
// Data events
onData?: (event: MapStyleDataEvent | MapSourceDataEvent) => void;
onStyleData?: (event: MapStyleDataEvent) => void;
onSourceData?: (event: MapSourceDataEvent) => void;
// Render events
onRender?: (event: MapEvent) => void;
onIdle?: (event: MapEvent) => void;
}Events related to camera position and view state changes.
/**
* Event fired when the map's view state changes
* Contains new view state and interaction information
*/
interface ViewStateChangeEvent {
/** New view state after the change */
viewState: ViewState;
/** Current interaction state causing the change */
interactionState: InteractionState;
/** Original DOM event that triggered the change */
originalEvent: Event;
}
/**
* Current camera view state
*/
interface ViewState {
/** Longitude at map center */
longitude: number;
/** Latitude at map center */
latitude: number;
/** Map zoom level */
zoom: number;
/** Map rotation bearing in degrees counter-clockwise from north */
bearing: number;
/** Map angle in degrees at which the camera is looking at the ground */
pitch: number;
/** Dimensions in pixels applied on each side of the viewport for shifting the vanishing point */
padding: PaddingOptions;
}
/**
* Information about current user interaction
*/
interface InteractionState {
inTransition?: boolean;
isDragging?: boolean;
isPanning?: boolean;
isZooming?: boolean;
isRotating?: boolean;
}Events fired by mouse interactions with the map.
/**
* Mouse event on the map containing position and feature information
*/
interface MapMouseEvent extends MapEvent {
/** Mouse position in screen coordinates */
point: Point;
/** Geographic coordinates of the event */
lngLat: LngLat;
/** Features at the event location */
features?: MapGeoJSONFeature[];
/** Original DOM mouse event */
originalEvent: MouseEvent;
}
/**
* Base map event interface
*/
interface MapEvent {
/** Event type identifier */
type: string;
/** Target map instance */
target: MapInstance;
/** Original DOM event if applicable */
originalEvent?: Event;
}Events fired by touch interactions on mobile devices.
/**
* Touch event on the map
*/
interface MapTouchEvent extends MapEvent {
/** Touch position in screen coordinates */
point: Point;
/** Geographic coordinates of the first touch */
lngLat: LngLat;
/** Array of all touch points */
points: Point[];
/** Array of geographic coordinates for all touches */
lngLats: LngLat[];
/** Features at the first touch location */
features?: MapGeoJSONFeature[];
/** Original DOM touch event */
originalEvent: TouchEvent;
}Events fired by mouse wheel interactions.
/**
* Mouse wheel event on the map
*/
interface MapWheelEvent extends MapEvent {
/** Wheel position in screen coordinates */
point: Point;
/** Geographic coordinates of the wheel event */
lngLat: LngLat;
/** Delta values from the wheel event */
deltaY: number;
deltaX?: number;
deltaZ?: number;
/** Original DOM wheel event */
originalEvent: WheelEvent;
}Events fired during box zoom interactions.
/**
* Box zoom event containing selection bounds
*/
interface MapBoxZoomEvent extends MapEvent {
/** Selection box bounds in screen coordinates */
boxZoomBounds: LngLatBounds;
/** Original DOM event */
originalEvent: MouseEvent;
}Events fired when map data is loaded or updated.
/**
* Event fired when map style data is loaded or updated
*/
interface MapStyleDataEvent extends MapEvent {
/** Type of style data that changed */
dataType: 'style' | 'sprite' | 'glyphs';
/** Whether this is the initial load */
isSourceLoaded?: boolean;
/** Source ID if applicable */
sourceId?: string;
/** Source data type if applicable */
sourceDataType?: 'metadata' | 'content' | 'visibility' | 'idle';
/** Tile coordinates if applicable */
tile?: any;
/** Coordinate information */
coord?: any;
}
/**
* Event fired when map source data is loaded or updated
*/
interface MapSourceDataEvent extends MapEvent {
/** Type of source data that changed */
dataType: 'source';
/** Whether this is the initial load */
isSourceLoaded: boolean;
/** Source ID that changed */
sourceId: string;
/** Source data type */
sourceDataType: 'metadata' | 'content' | 'visibility' | 'idle';
/** Tile coordinates if applicable */
tile?: any;
/** Coordinate information */
coord?: any;
}
/**
* Event fired when a style image is missing
*/
interface MapStyleImageMissingEvent extends MapEvent {
/** ID of the missing image */
id: string;
}Events fired when errors occur during map operations.
/**
* Error event containing error information
*/
interface ErrorEvent extends MapEvent {
/** Error object with details */
error: Error;
/** Error message */
message?: string;
/** Error source or context */
source?: string;
}Events specific to individual map components.
/**
* Marker-related events
*/
interface MarkerEvent {
/** Event type */
type: string;
/** Target marker instance */
target: MarkerInstance;
/** Original DOM event */
originalEvent: Event;
}
/**
* Marker drag events with position information
*/
interface MarkerDragEvent extends MarkerEvent {
/** New marker position */
lngLat: LngLat;
}
/**
* Popup-related events
*/
interface PopupEvent {
/** Event type */
type: string;
/** Target popup instance */
target: PopupInstance;
/** Original DOM event if applicable */
originalEvent?: Event;
}
/**
* Geolocation control events
*/
interface GeolocateEvent {
/** Event type */
type: string;
/** Target geolocate control */
target: GeolocateControlInstance;
}
/**
* Successful geolocation result
*/
interface GeolocateResultEvent extends GeolocateEvent {
/** Geolocation coordinates */
coords: GeolocationCoordinates;
/** Timestamp of the geolocation */
timestamp: number;
}
/**
* Geolocation error event
*/
interface GeolocateErrorEvent extends GeolocateEvent {
/** Geolocation error */
error: GeolocationPositionError;
}Core geometric types used throughout the event system.
/**
* 2D point in screen coordinates
*/
interface Point {
x: number;
y: number;
}
/**
* Point-like values that can be converted to Point
*/
type PointLike = Point | [number, number];
/**
* Geographic coordinates
*/
interface LngLat {
lng: number;
lat: number;
}
/**
* Longitude/latitude-like values that can be converted to LngLat
*/
type LngLatLike =
| LngLat
| [number, number]
| { lon: number; lat: number }
| { longitude: number; latitude: number };
/**
* Geographic bounds rectangle
*/
interface LngLatBounds {
_sw: LngLat;
_ne: LngLat;
/** Get southwest corner */
getSouthWest(): LngLat;
/** Get northeast corner */
getNorthEast(): LngLat;
/** Get northwest corner */
getNorthWest(): LngLat;
/** Get southeast corner */
getSouthEast(): LngLat;
/** Get center point */
getCenter(): LngLat;
/** Check if bounds contain a point */
contains(lnglat: LngLatLike): boolean;
/** Extend bounds to include a point */
extend(lnglat: LngLatLike): LngLatBounds;
}
/**
* Bounds-like values that can be converted to LngLatBounds
*/
type LngLatBoundsLike =
| LngLatBounds
| [LngLatLike, LngLatLike]
| [number, number, number, number];
/**
* Padding options for map viewport
*/
interface PaddingOptions {
top?: number;
bottom?: number;
left?: number;
right?: number;
}
/**
* GeoJSON feature with additional map-specific properties
*/
interface MapGeoJSONFeature {
type: 'Feature';
id?: string | number;
properties: { [key: string]: any };
geometry: any;
layer?: { id: string; type: string; source: string; 'source-layer'?: string };
source?: string;
sourceLayer?: string;
state?: { [key: string]: any };
}Types for integrating with underlying map libraries.
/**
* Map library interface for Mapbox/MapLibre compatibility
*/
interface MapLib {
Map: any;
Marker: any;
Popup: any;
AttributionControl: any;
FullscreenControl: any;
GeolocateControl: any;
NavigationControl: any;
ScaleControl: any;
TerrainControl?: any; // MapLibre only
LogoControl?: any; // MapLibre only
version: string;
}
/**
* Map instance type combining library-specific methods
*/
interface MapInstance {
// Core map methods
getContainer(): HTMLElement;
getCanvasContainer(): HTMLElement;
getCanvas(): HTMLCanvasElement;
// View state methods
getCenter(): LngLat;
setCenter(center: LngLatLike): MapInstance;
getZoom(): number;
setZoom(zoom: number): MapInstance;
getBearing(): number;
setBearing(bearing: number): MapInstance;
getPitch(): number;
setPitch(pitch: number): MapInstance;
getPadding(): PaddingOptions;
setPadding(padding: PaddingOptions): MapInstance;
// Bounds methods
getBounds(): LngLatBounds;
setMaxBounds(bounds?: LngLatBoundsLike): MapInstance;
getMaxBounds(): LngLatBounds | null;
fitBounds(bounds: LngLatBoundsLike, options?: any): MapInstance;
fitScreenCoordinates(p0: PointLike, p1: PointLike, bearing: number, options?: any): MapInstance;
// Conversion methods
project(lnglat: LngLatLike): Point;
unproject(point: PointLike): LngLat;
// Style methods
getStyle(): any;
setStyle(style: any): MapInstance;
// Source methods
addSource(id: string, source: any): MapInstance;
removeSource(id: string): MapInstance;
getSource(id: string): any;
// Layer methods
addLayer(layer: any, beforeId?: string): MapInstance;
removeLayer(id: string): MapInstance;
getLayer(id: string): any;
moveLayer(id: string, beforeId?: string): MapInstance;
// Feature methods
queryRenderedFeatures(pointOrBox?: PointLike | [PointLike, PointLike], options?: any): MapGeoJSONFeature[];
querySourceFeatures(sourceId: string, options?: any): MapGeoJSONFeature[];
// Control methods
addControl(control: IControl, position?: ControlPosition): MapInstance;
removeControl(control: IControl): MapInstance;
// Event methods
on(type: string, listener: Function): MapInstance;
off(type: string, listener: Function): MapInstance;
once(type: string, listener: Function): MapInstance;
fire(type: string, properties?: any): MapInstance;
// Lifecycle methods
remove(): void;
resize(): MapInstance;
redraw(): MapInstance;
}
/**
* Control interface for custom map controls
*/
interface IControl {
onAdd(map: MapInstance): HTMLElement;
onRemove(map: MapInstance): void;
getDefaultPosition?(): ControlPosition;
}
/**
* Control position options
*/
type ControlPosition =
| 'top-left'
| 'top-right'
| 'bottom-left'
| 'bottom-right';
/**
* Component instance types
*/
interface MarkerInstance {
getLngLat(): LngLat;
setLngLat(lnglat: LngLatLike): MarkerInstance;
getOffset(): Point;
setOffset(offset: PointLike): MarkerInstance;
addTo(map: MapInstance): MarkerInstance;
remove(): MarkerInstance;
togglePopup(): MarkerInstance;
getPopup(): PopupInstance;
setPopup(popup?: PopupInstance): MarkerInstance;
bindPopup(popup: PopupInstance): MarkerInstance;
unbindPopup(): MarkerInstance;
on(type: string, listener: Function): MarkerInstance;
off(type: string, listener: Function): MarkerInstance;
}
interface PopupInstance {
addTo(map: MapInstance): PopupInstance;
isOpen(): boolean;
remove(): PopupInstance;
getLngLat(): LngLat;
setLngLat(lnglat: LngLatLike): PopupInstance;
setHTML(html: string): PopupInstance;
setText(text: string): PopupInstance;
setDOMContent(htmlNode: Node): PopupInstance;
getElement(): HTMLElement;
on(type: string, listener: Function): PopupInstance;
off(type: string, listener: Function): PopupInstance;
}
interface GeolocateControlInstance extends IControl {
trigger(): boolean;
}Handling View State Changes:
import React from 'react';
import Map, { ViewStateChangeEvent } from 'react-map-gl/mapbox';
function ViewStateExample() {
const handleMove = (event: ViewStateChangeEvent) => {
console.log('New position:', {
longitude: event.viewState.longitude,
latitude: event.viewState.latitude,
zoom: event.viewState.zoom
});
if (event.interactionState.isDragging) {
console.log('User is dragging the map');
}
};
return (
<Map
initialViewState={{longitude: -100, latitude: 40, zoom: 4}}
onMove={handleMove}
onMoveStart={() => console.log('Move started')}
onMoveEnd={() => console.log('Move ended')}
/>
);
}Handling Click Events with Feature Queries:
import React from 'react';
import Map, { MapMouseEvent } from 'react-map-gl/mapbox';
function ClickExample() {
const handleClick = (event: MapMouseEvent) => {
console.log('Clicked at:', event.lngLat);
console.log('Screen position:', event.point);
if (event.features && event.features.length > 0) {
console.log('Clicked features:', event.features);
console.log('First feature properties:', event.features[0].properties);
}
};
return (
<Map
initialViewState={{longitude: -100, latitude: 40, zoom: 4}}
onClick={handleClick}
interactiveLayerIds={['data-layer']} // Only fire click events for this layer
/>
);
}Error Handling:
import React from 'react';
import Map, { ErrorEvent } from 'react-map-gl/mapbox';
function ErrorHandlingExample() {
const handleError = (event: ErrorEvent) => {
console.error('Map error:', event.error.message);
// Handle specific error types
if (event.error.message.includes('access token')) {
console.error('Invalid access token provided');
} else if (event.error.message.includes('style')) {
console.error('Style loading error');
}
};
return (
<Map
initialViewState={{longitude: -100, latitude: 40, zoom: 4}}
mapStyle="mapbox://styles/mapbox/streets-v12"
mapboxAccessToken="YOUR_TOKEN"
onError={handleError}
/>
);
}Install with Tessl CLI
npx tessl i tessl/npm-react-map-gl