mapbox-gl-draw

How to disable midpoint selection, dragging for LineString types (draw_line_string mode)


How do I disable the ability for a user to select (direct_select) the midpoint of a LineString in mapbox-gl-draw? I have a custom mode for "annotations", which should only allow for LineStrings with 2 vertices.

I've tried some of the lifecycle hooks in custom modes (https://github.com/mapbox/mapbox-gl-draw/blob/master/docs/MODES.md), specifically for draw_line_string, including onDrag. My problem is I don't want the drag point to exist at all (it would involve the user seeing a midpoint, dragging that vertex, and then seeing it snap back).

I've also tried dealing with the draw styles, but they are general to all midpoints (include polygons).

A third way might be to invalidate this outside of mapbox-gl-draw, in my framework, but I'd like to avoid even the ability to select a midpoint at all.


Solution

  • You can achieve that by creating a custom mode from direct_select mode:

    import * as MapboxDraw from '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw';
    import createSupplementaryPoints from '@mapbox/mapbox-gl-draw/src/lib/create_supplementary_points';
    import Constants from '@mapbox/mapbox-gl-draw/src/constants';
    
    const DirectSelectWithoutMiddleVertexMode = MapboxDraw.modes.direct_select;
    
    DirectSelectWithoutMiddleVertexMode.toDisplayFeatures = function (state, geojson, push) {
      if (state.featureId === geojson.properties.id) {
        geojson.properties.active = Constants.activeStates.ACTIVE;
        push(geojson);
        createSupplementaryPoints(geojson, {
          map: this.map,
          midpoints: false,
          selectedPaths: state.selectedCoordPaths
        }).forEach(push);
      } else {
        geojson.properties.active = Constants.activeStates.INACTIVE;
        push(geojson);
      }
      this.fireActionable(state);
    };
    
    export default DirectSelectWithoutMiddleVertexMode;
    

    The only thing to do is to set the midpoints property to false that avoids the midpoint creation.

    After that, use the custom mode to override direct_select mode in the draw options :

    import DirectSelectWithoutMiddleVertexMode from './DirectSelectWithoutMiddleVertexMode';
    
    const drawOptions = {
        modes: Object.assign({
            direct_select: DirectSelectWithoutMiddleVertexMode
        }, MapboxDraw.modes)
    };
    
    const draw = new MapboxDraw(drawOptions);