Mapbox GL Draw

repository·main·Indexed 21 days ago

https://github.com/mapbox/mapbox-gl-draw

A plugin for Mapbox GL JS that provides tools for drawing and editing geographic features such as points, lines, and polygons directly on a map. It includes a set of drawing modes (simple_select, direct_select, draw_line_string, draw_polygon, and draw_point), an API for managing GeoJSON features, and an extensible architecture for creating custom interaction modes.

Tokens
9.4K
Snippets
23
Records
45
Agent score
77%

What's inside @mapbox/mapbox-gl-draw

  1. Extend functionality with custom modes

    main
    Mapbox Draw is designed to be extensible. Instead of modifying the core library, you can implement new interactions by creating custom modes. This allows you to experiment with new drawing or editing behaviors before they are considered for the core library.
  2. Understand MapboxDraw modes

    main

    MapboxDraw operates in different modes that define user interaction. Mode names are available via the Draw.modes enum.

    • simple_select (Draw.modes.SIMPLE_SELECT): Default mode. Allows selecting, deleting, and dragging features.
    • direct_select (Draw.modes.DIRECT_SELECT): Allows selecting, deleting, and dragging vertices of a selected line or polygon. Triggered when a user clicks a vertex in simple_select mode.
    • draw_line_string (Draw.modes.DRAW_LINE_STRING): Mode for drawing a LineString feature.
    • draw_polygon (Draw.modes.DRAW_POLYGON): Mode for drawing a Polygon feature.
    • draw_point (Draw.modes.DRAW_POINT): Mode for drawing a Point feature.
  3. How modes work in Mapbox Draw

    main

    In Mapbox Draw, modes are abstractions used to group sets of user interactions into a single behavior. For example, the built-in draw_polygon mode manages all interactions required to draw a polygon, while simple_select manages interactions for selecting features.

    Developers can extend Mapbox Draw by writing custom modes and registering them via the modes option in the MapboxDraw constructor. This allows for complete control over how map interactions (clicks, drags, key presses) translate into drawing or editing actions.

    var draw = new MapboxDraw({
      defaultMode: 'my_custom_mode',
      modes: Object.assign({
        my_custom_mode: MyCustomMode,
      }, MapboxDraw.modes),
    });
  4. Import @mapbox/mapbox-gl-draw

    main

    Depending on your environment, use one of the following methods to import the library.

    When using modules:

    import mapboxgl from 'mapbox-gl';
    import MapboxDraw from "@mapbox/mapbox-gl-draw";

    When using a CDN:

    <script src='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.4.3/mapbox-gl-draw.js'></script>
  5. Include @mapbox/mapbox-gl-draw CSS

    main

    Mapbox Draw requires its CSS to be included in your build to render correctly.

    When using modules: Import the CSS file directly in your JavaScript entry point.

    When using CDN: Include the stylesheet link in your HTML.

    // When using modules
    import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css'
    <!-- When using CDN -->
    <link rel='stylesheet' href='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.4.3/mapbox-gl-draw.css' type='text/css' />
  6. Write a custom mode for Mapbox Draw

    main

    To create a custom mode, define an object containing lifecycle functions.

    1. toDisplayFeatures (Required): This is the only mandatory function. It decides which features from the data store are rendered on the map. It receives the current geojson and a display callback function. You must call display(geojson) (or pass modified versions) to ensure features appear on the map.
    2. onSetup: Triggered when transitioning into the mode. It receives opts (passed via draw.changeMode('mode', opts)) and should return a state object. This state object is then passed as the first argument to all other lifecycle functions.
    3. Interaction Handlers: Implement functions like onClick, onDrag, onMouseMove, onKeyDown, etc., to respond to user input. Within these, you can use this.newFeature(geojson) to create a DrawFeature and this.addFeature(feature) to add it to the map.
    4. Mode Switching: Use this.changeMode('mode_name') within a lifecycle function to transition to a different mode (e.g., returning to simple_select).
    var LotsOfPointsMode = {};
    
    // 1. Setup state
    LotsOfPointsMode.onSetup = function(opts) {
      var state = {};
      state.count = opts.count || 0;
      return state;
    };
    
    // 2. Handle interactions
    LotsOfPointsMode.onClick = function(state, e) {
      var point = this.newFeature({
        type: 'Feature',
        properties: { count: state.count },
        geometry: { type: 'Point', coordinates: [e.lngLat.lng, e.lngLat.lat] }
      });
      this.addFeature(point);
    };
    
    LotsOfPointsMode.onKeyUp = function(state, e) {
      if (e.keyCode === 27) return this.changeMode('simple_select');
    };
    
    // 3. Required: Define how to render
    LotsOfPointsMode.toDisplayFeatures = function(state, geojson, display) {
      display(geojson);
    };
    
    // 4. Register the mode
    var draw = new MapboxDraw({
      defaultMode: 'lots_of_points',
      modes: Object.assign({
        lots_of_points: LotsOfPointsMode,
      }, MapboxDraw.modes),
    });
  7. Initialize and add MapboxDraw to a Mapbox GL JS map

    main

    To use Draw, you must first create a Mapbox GL JS map instance, then instantiate MapboxDraw with your desired options, and finally add the Draw control to the map using map.addControl().

    Important: You must only interact with the Draw API (e.g., calling .add()) after the map's load event has fired.

    // Create a Mapbox GL JS map
    var map = new Map(mapOptions);
    
    // Create a Draw control
    var draw = new MapboxDraw(drawOptions);
    
    // Add the Draw control to your map
    map.addControl(draw);
    
    // Interact with Draw only after the map has loaded
    map.on('load', function() {
      draw.add({ .. });
    });
  8. Listen to Mapbox GL Draw events

    main

    All events emitted by Draw are namespaced with draw. and are emitted from the Mapbox GL JS map object. These events are triggered by user interactions.

    Note on Programmatic Calls: If you invoke a Draw API function programmatically (e.g., draw.delete()), the event directly corresponding to that function (e.g., draw.delete) will not fire. However, subsequent indirect events (e.g., draw.selectionchange) may still fire.

    To listen for events, use the standard Mapbox GL JS .on() method on your map instance.

    map.on('draw.create', function (e) {
      console.log(e.features);
    });
  9. Style Mapbox GL Draw layers

    main

    Draw uses a Mapbox GL Style. When creating custom styles for Draw, follow these rules:

    1. Do NOT provide a source: Draw manages its own sources (mapbox-gl-draw-hot and mapbox-gl-draw-cold) to optimize performance. It will provide a source for you automatically.
    2. You MUST provide an id: Draw will append .hot and .cold suffixes to your provided ID.

    Available Feature Properties for Styling:

    PropertyValuesDescription
    metafeature, midpoint, vertexmidpoint and vertex are used for handles; feature is used for all features.
    activetrue, false (strings)Indicates if a feature is 'selected' in the current mode.
    modesimple_select, direct_select, draw_point, draw_line_string, draw_polygonThe current Draw mode.

    If opts.userProperties is set to true, user properties are available via the user_ prefix.

  10. Configure MapboxDraw options

    main

    When instantiating MapboxDraw, you can pass an optional configuration object. All options are optional:

    • keybindings (boolean, default: true): Enable/disable keyboard interactions.
    • touchEnabled (boolean, default: true): Enable/disable touch interactions.
    • boxSelect (boolean, default: true): Enable/disable box selection via shift+click+drag.
    • clickBuffer (number, default: 2): Pixel radius around features/vertices for click response.
    • touchBuffer (number, default: 25): Pixel radius around features/vertices for touch response.
    • controls (Object): Toggle individual controls: point, line_string, polygon, trash, combine_features, and uncombine_features.
    • displayControlsDefault (boolean, default: true): The default state for the controls object.
    • styles (Array<Object>): Custom map styles for Draw features.
    • modes (Object): Override default modes with custom ones.
    • defaultMode (string, default: 'simple_select'): The initial mode the user enters.
    • userProperties (boolean, default: false): If true, feature properties are prefixed with user_ for styling (e.g., ['==', 'user_custom_label', 'Example']).
    • suppressAPIEvents (boolean, default: true): If false, Draw will emit events when API methods are called.