Skip to content

Map Interaction Handlers

Relevant source files

Purpose and Scope

This document describes the Handler system in Leaflet, which provides modular, enable/disable-able interaction behaviors for maps and layers. Handlers translate raw user input (mouse, touch, keyboard) into meaningful map operations like dragging, zooming, and selection.

For information about the underlying DOM event normalization and the Draggable utility class, see DOM Utilities and Event Handling. For UI controls like zoom buttons and layer switchers, see Controls.


Handler Base Class Pattern

All interaction handlers in Leaflet extend from the Handler base class, which provides a consistent interface for managing interactive behaviors. The base class is located at src/core/Handler.js

Core Handler Interface

SVG
100%

Handler Lifecycle

MethodPurposeWhen Called
initialize(map)Constructor, stores map referenceHandler creation
enable()Activates handler, calls addHooks()User enables feature or default initialization
disable()Deactivates handler, calls removeHooks()User disables feature or cleanup
enabled()Returns activation stateStatus check
addHooks()Attaches event listeners, creates DOM elementsInside enable()
removeHooks()Detaches event listeners, cleans upInside disable()

Map-Level Handlers

The LeafletMap class instantiates and manages several handlers for core map interactions. These handlers are exposed as properties on the map instance, allowing runtime control.

Handler Properties on Map

SVG
100%

Usage Pattern

// Disable dragging
map.dragging.disable();

// Check if scroll wheel zoom is enabled
if (map.scrollWheelZoom.enabled()) {
    // ...
}

// Re-enable box zoom
map.boxZoom.enable();

Individual Handler Implementations

DragHandler

File: src/map/handler/DragHandler.js
Property: map.dragging
Purpose: Enables panning the map by clicking and dragging

Behavior:

  • Listens for pointer down events on the map container
  • Creates a Draggable instance to handle drag lifecycle
  • Translates pixel movement into map panning
  • Supports inertia (continued movement after release)
  • Fires movestart, move, moveend events on the map

Key Implementation Details:

  • Uses the Draggable class for low-level drag mechanics (see DOM Utilities and Event Handling)
  • Calculates new map center based on pixel offset
  • Handles inertial deceleration with configurable easing

DoubleClickZoomHandler

File: src/map/handler/DoubleClickZoomHandler.js
Property: map.doubleClickZoom
Purpose: Zooms in one level on double-click

Behavior:

  • Listens for dblclick events on the map
  • Zooms in by one level (or zooms out if shift key is held)
  • Centers zoom on the clicked point
  • Can be configured with animation options

ScrollWheelZoomHandler

File: src/map/handler/ScrollWheelZoomHandler.js
Property: map.scrollWheelZoom
Purpose: Zooms the map using mouse wheel or trackpad

Behavior:

  • Listens for wheel events (normalized across browsers)
  • Accumulates delta values to determine zoom direction and magnitude
  • Supports smooth zooming (fractional zoom levels during animation)
  • Centers zoom on cursor position
  • Includes throttling to prevent excessive zoom events

Configuration Options:

  • wheelDebounceTime: Delay before processing accumulated wheel events
  • wheelPxPerZoomLevel: Sensitivity of wheel input

BoxZoomHandler

File: src/map/handler/BoxZoomHandler.js
Property: map.boxZoom
Purpose: Enables zoom-to-selection by shift+dragging

Behavior:

  • Activates when shift key is held during mouse down
  • Draws a visual selection rectangle on the map
  • On release, zooms to fit the selected bounds
  • Temporarily disables the DragHandler while active

Implementation:

  • Creates a temporary DOM element for the selection box
  • Uses CSS transforms for positioning
  • Calculates LatLngBounds from pixel coordinates
  • Calls map.fitBounds() on completion

KeyboardHandler

File: src/map/handler/KeyboardHandler.js
Property: map.keyboard
Purpose: Enables keyboard navigation and zoom

Behavior:

  • Listens for keydown events on the map container
  • Arrow keys: Pan the map
  • + / - keys: Zoom in/out
  • Requires map container to have focus

Key Bindings:

KeyAction
← → ↑ ↓Pan map in direction
+ or =Zoom in
- or _Zoom out

Accessibility Considerations:

  • Map container must be focusable (tabindex attribute)
  • Essential for keyboard-only users

PinchZoomHandler (TouchZoom)

File: src/map/handler/PinchZoomHandler.js
Property: map.touchZoom
Purpose: Enables pinch-to-zoom on touch devices

Behavior:

  • Detects two-finger touch events
  • Calculates distance change between touch points
  • Translates to zoom level change
  • Centers zoom between the two touch points
  • Works in conjunction with touch drag for panning

Implementation Details:

  • Tracks touchstart, touchmove, touchend events
  • Calculates pinch center point as midpoint between fingers
  • Uses distance ratio to determine zoom delta
  • Prevents default browser zoom behavior

TapHoldHandler

File: src/map/handler/TapHoldHandler.js
Property: map.tap
Purpose: Handles tap and long-press events on touch devices

Behavior:

  • Distinguishes between tap, double-tap, and long-press
  • Fires click and dblclick events for taps
  • Fires contextmenu event for long-press
  • Provides touch-friendly alternatives to mouse events

Timing Thresholds:

  • Tap duration: < 300ms
  • Long press duration: > 500ms (configurable)
  • Double tap window: 300ms between taps

Layer-Level Handlers: MarkerDrag

While most handlers are attached to the map, some layers have their own handlers. The MarkerDrag handler enables dragging individual markers.

MarkerDrag Architecture

SVG
100%

Sources: src/layer/marker/Marker.Drag.js1-159

MarkerDrag Implementation

Initialization: src/layer/marker/Marker.Drag.js26-29

// MarkerDrag stores reference to both marker and map
initialize(marker) {
    super.initialize(marker._map);
    this._marker = marker;
}

Adding Hooks: src/layer/marker/Marker.Drag.js31-46

  • Creates a Draggable instance for the marker icon
  • Attaches listeners for drag lifecycle events
  • Adds leaflet-marker-draggable CSS class to icon

Removing Hooks: src/layer/marker/Marker.Drag.js48-57

  • Detaches all event listeners
  • Disables the Draggable instance
  • Removes CSS class

Auto-Pan Behavior

When dragging a marker near the map edge, MarkerDrag automatically pans the map to keep the marker visible.

Auto-Pan Implementation: src/layer/marker/Marker.Drag.js63-97

SVG
100%

Configuration:

  • autoPan: Boolean option to enable/disable
  • autoPanPadding: Pixel buffer from edge (default: Point(50, 50))
  • autoPanSpeed: Pixels per frame

Drag Event Flow

SVG
100%

Handler Registration and Initialization

Map handlers are typically registered during map initialization. The map constructor instantiates each handler and stores it as a property.

Handler Initialization Pattern

SVG
100%

Default Handler States

Map options control which handlers are enabled by default:

OptionHandlerDefault
draggingDragHandlertrue (desktop), true (mobile)
touchZoomPinchZoomHandlertrue (mobile)
scrollWheelZoomScrollWheelZoomHandlertrue (desktop)
doubleClickZoomDoubleClickZoomHandlertrue
boxZoomBoxZoomHandlertrue (desktop)
keyboardKeyboardHandlertrue
tapTapHoldHandlertrue (mobile)

Handler Coordination and Interaction

Handlers may need to coordinate with each other to prevent conflicting interactions.

Handler Interaction Examples

Box Zoom and Drag:

  • BoxZoomHandler disables DragHandler when shift is held
  • Prevents simultaneous box selection and map panning
  • Re-enables DragHandler on completion

Scroll Wheel and Keyboard:

  • Both handlers can zoom independently
  • No conflict as they respond to different input sources

Touch Handlers:

  • PinchZoomHandler, TapHoldHandler, and touch drag coordinate
  • Touch event handling requires careful touch point tracking
  • Prevents unintended gestures during pinch zoom

Event Flow Integration

SVG
100%

Custom Handler Development

Developers can create custom handlers by extending the Handler base class.

Custom Handler Template

import {Handler} from './core/Handler.js';

class CustomHandler extends Handler {
    addHooks() {
        // Attach event listeners
        this._map.on('click', this._onClick, this);
    }
    
    removeHooks() {
        // Clean up event listeners
        this._map.off('click', this._onClick, this);
    }
    
    _onClick(e) {
        // Handle the event
        console.log('Custom handler clicked at', e.latlng);
    }
}

// Add to map
map.customHandler = new CustomHandler(map);
map.customHandler.enable();

Best Practices

  1. Always clean up in removeHooks(): Remove all event listeners and DOM elements
  2. Store map reference: Access via this._map
  3. Fire appropriate events: Let users listen to handler actions
  4. Respect other handlers: Check if interaction conflicts with existing handlers
  5. Use DomEvent for cross-browser compatibility: Don't attach listeners directly

Summary

The Handler system provides a modular, consistent architecture for map interactions:

ComponentPurpose
Handler base classDefines enable/disable interface
Map handlersPan, zoom, select via mouse/keyboard
Touch handlersPinch, tap, long-press for mobile
Layer handlersDrag markers and other interactive layers
DomEvent integrationCross-browser event normalization (see #4.1)
Draggable integrationLow-level drag mechanics (see #4.1)

All handlers follow the same lifecycle pattern (addHooks/removeHooks) and can be controlled at runtime via enable()/disable() methods, providing fine-grained control over map behavior.