UNPKG

mapbox-gl-draw-snap-mode

Version:
161 lines (129 loc) 4.27 kB
import MapboxDraw from "@mapbox/mapbox-gl-draw"; import { addPointToVertices, createSnapList, getGuideFeature, IDS, shouldHideGuide, snap, } from "./../utils/index.js"; const { doubleClickZoom } = MapboxDraw.lib; const { geojsonTypes, modes, cursors } = MapboxDraw.constants; const DrawLine = MapboxDraw.modes.draw_line_string; const SnapLineMode = { ...DrawLine }; SnapLineMode.onSetup = function (options) { const line = this.newFeature({ type: geojsonTypes.FEATURE, properties: {}, geometry: { type: geojsonTypes.LINE_STRING, coordinates: [[]], }, }); const verticalGuide = this.newFeature(getGuideFeature(IDS.VERTICAL_GUIDE)); const horizontalGuide = this.newFeature( getGuideFeature(IDS.HORIZONTAL_GUIDE) ); this.addFeature(line); this.addFeature(verticalGuide); this.addFeature(horizontalGuide); const selectedFeatures = this.getSelected(); this.clearSelectedFeatures(); doubleClickZoom.disable(this); const [snapList, vertices] = createSnapList( this.map, this._ctx.api, line, this._ctx.options.snapOptions?.snapGetFeatures ); const state = { map: this.map, line, currentVertexPosition: 0, vertices, snapList, selectedFeatures, verticalGuide, horizontalGuide, direction: "forward", // expected by DrawLineString }; state.options = this._ctx.options; const moveendCallback = () => { const [snapList, vertices] = createSnapList( this.map, this._ctx.api, line, this._ctx.options.snapOptions?.snapGetFeatures ); state.vertices = vertices; state.snapList = snapList; }; // for removing listener later on close state["moveendCallback"] = moveendCallback; const optionsChangedCallback = (options) => { state.options = options; }; // for removing listener later on close state["optionsChangedCallback"] = optionsChangedCallback; this.map.on("moveend", moveendCallback); this.map.on("draw.snap.options_changed", optionsChangedCallback); return state; }; SnapLineMode.onClick = function (state) { // We save some processing by rounding on click, not mousemove const lng = state.snappedLng; const lat = state.snappedLat; // End the drawing if this click is on the previous position // Note: not bothering with 'direction' if (state.currentVertexPosition > 0) { const lastVertex = state.line.coordinates[state.currentVertexPosition - 1]; state.lastVertex = lastVertex; if (lastVertex[0] === lng && lastVertex[1] === lat) { return this.changeMode(modes.SIMPLE_SELECT, { featureIds: [state.line.id], }); } } // const point = state.map.project({ lng: lng, lat: lat }); addPointToVertices(state.map, state.vertices, { lng, lat }); state.line.updateCoordinate(state.currentVertexPosition, lng, lat); state.currentVertexPosition++; state.line.updateCoordinate(state.currentVertexPosition, lng, lat); }; SnapLineMode.onMouseMove = function (state, e) { const { lng, lat } = snap(state, e); state.line.updateCoordinate(state.currentVertexPosition, lng, lat); state.snappedLng = lng; state.snappedLat = lat; if ( state.lastVertex && state.lastVertex[0] === lng && state.lastVertex[1] === lat ) { this.updateUIClasses({ mouse: cursors.POINTER }); // cursor options: // ADD: "add" // DRAG: "drag" // MOVE: "move" // NONE: "none" // POINTER: "pointer" } else { this.updateUIClasses({ mouse: cursors.ADD }); } }; // This is 'extending' DrawLine.toDisplayFeatures SnapLineMode.toDisplayFeatures = function (state, geojson, display) { if (shouldHideGuide(state, geojson)) return; // This relies on the the state of SnapLineMode being similar to DrawLine DrawLine.toDisplayFeatures(state, geojson, display); }; // This is 'extending' DrawLine.onStop SnapLineMode.onStop = function (state) { this.deleteFeature(IDS.VERTICAL_GUIDE, { silent: true }); this.deleteFeature(IDS.HORIZONTAL_GUIDE, { silent: true }); // remove moveend callback this.map.off("moveend", state.moveendCallback); // This relies on the the state of SnapLineMode being similar to DrawLine DrawLine.onStop.call(this, state); }; export default SnapLineMode;