diff --git a/docs/api-reference/layers/editable-geojson-layer.md b/docs/api-reference/layers/editable-geojson-layer.md index 66631bdb6..0ed335b29 100644 --- a/docs/api-reference/layers/editable-geojson-layer.md +++ b/docs/api-reference/layers/editable-geojson-layer.md @@ -145,6 +145,10 @@ The `onEdit` event is the core event provided by this layer and must be handled * `editContext` (Object): `null` or an object containing additional context about the edit. This is populated by the active mode, see [modes overview](../modes/overview.md). +#### `onCancelPan` (Function, optional) + +The `onCancelPan` event is called when map panning should be cancelled to enable feature dragging interactions while editing. + ### Guide style properties and data getters #### `editHandleType`: (String, optional) diff --git a/modules/edit-modes/src/lib/extrude-mode.ts b/modules/edit-modes/src/lib/extrude-mode.ts index 2668c83e9..af9a079b6 100644 --- a/modules/edit-modes/src/lib/extrude-mode.ts +++ b/modules/edit-modes/src/lib/extrude-mode.ts @@ -3,6 +3,7 @@ import { generatePointsParallelToLinePoints, getPickedEditHandle, getPickedIntermediateEditHandle, + shouldCancelPan, } from '../utils'; import { FeatureCollection } from '../geojson-types'; import { ModeProps, StartDraggingEvent, StopDraggingEvent, DraggingEvent } from '../types'; @@ -57,8 +58,11 @@ export class ExtrudeMode extends ModifyMode { } handleStartDragging(event: StartDraggingEvent, props: ModeProps) { - const selectedFeatureIndexes = props.selectedIndexes; + if (shouldCancelPan(event)) { + event.cancelPan(); + } + const selectedFeatureIndexes = props.selectedIndexes; const editHandle = getPickedIntermediateEditHandle(event.picks); if (selectedFeatureIndexes.length && editHandle) { const { positionIndexes, featureIndex } = editHandle.properties; diff --git a/modules/edit-modes/src/lib/modify-mode.ts b/modules/edit-modes/src/lib/modify-mode.ts index 6a7dcf2c0..222fd2c81 100644 --- a/modules/edit-modes/src/lib/modify-mode.ts +++ b/modules/edit-modes/src/lib/modify-mode.ts @@ -10,6 +10,7 @@ import { getPickedIntermediateEditHandle, updateRectanglePosition, NearestPointType, + shouldCancelPan, } from '../utils'; import { LineString, Point, Polygon, FeatureCollection, FeatureOf } from '../geojson-types'; import { @@ -245,8 +246,11 @@ export class ModifyMode extends GeoJsonEditMode { } handleStartDragging(event: StartDraggingEvent, props: ModeProps) { - const selectedFeatureIndexes = props.selectedIndexes; + if (shouldCancelPan(event)) { + event.cancelPan(); + } + const selectedFeatureIndexes = props.selectedIndexes; const editHandle = getPickedIntermediateEditHandle(event.picks); if (selectedFeatureIndexes.length && editHandle) { const editHandleProperties = editHandle.properties; diff --git a/modules/edit-modes/src/lib/resize-circle-mode.ts b/modules/edit-modes/src/lib/resize-circle-mode.ts index 1736fd9e9..10009014f 100644 --- a/modules/edit-modes/src/lib/resize-circle-mode.ts +++ b/modules/edit-modes/src/lib/resize-circle-mode.ts @@ -177,6 +177,7 @@ export class ResizeCircleMode extends GeoJsonEditMode { handleStartDragging(event: StartDraggingEvent, props: ModeProps) { if (this._selectedEditHandle) { + event.cancelPan(); this._isResizing = true; } } diff --git a/modules/edit-modes/src/lib/rotate-mode.ts b/modules/edit-modes/src/lib/rotate-mode.ts index 9e76d1a6b..c66996548 100644 --- a/modules/edit-modes/src/lib/rotate-mode.ts +++ b/modules/edit-modes/src/lib/rotate-mode.ts @@ -125,6 +125,7 @@ export class RotateMode extends GeoJsonEditMode { handleStartDragging(event: StartDraggingEvent, props: ModeProps) { if (this._selectedEditHandle) { + event.cancelPan(); this._isRotating = true; this._geometryBeingRotated = this.getSelectedFeaturesAsFeatureCollection(props); } diff --git a/modules/edit-modes/src/lib/scale-mode.ts b/modules/edit-modes/src/lib/scale-mode.ts index 169e6b16e..353de310c 100644 --- a/modules/edit-modes/src/lib/scale-mode.ts +++ b/modules/edit-modes/src/lib/scale-mode.ts @@ -147,6 +147,7 @@ export class ScaleMode extends GeoJsonEditMode { handleStartDragging(event: StartDraggingEvent, props: ModeProps) { if (this._selectedEditHandle) { + event.cancelPan(); this._isScaling = true; this._geometryBeingScaled = this.getSelectedFeaturesAsFeatureCollection(props); } diff --git a/modules/edit-modes/src/lib/transform-mode.ts b/modules/edit-modes/src/lib/transform-mode.ts index a5d3b031c..3af98b85d 100644 --- a/modules/edit-modes/src/lib/transform-mode.ts +++ b/modules/edit-modes/src/lib/transform-mode.ts @@ -28,6 +28,10 @@ export class TransformMode extends CompositeMode { let translateMode = null; const filteredModes = []; + if (event.picks.length) { + event.cancelPan(); + } + // If the user selects a scaling edit handle that overlaps with part of the selected feature, // it is possible for both scale and translate actions to be triggered. This logic prevents // this simultaneous action trigger from happening by putting a higher priority on scaling diff --git a/modules/edit-modes/src/lib/translate-mode.ts b/modules/edit-modes/src/lib/translate-mode.ts index 21602041a..f71939e58 100644 --- a/modules/edit-modes/src/lib/translate-mode.ts +++ b/modules/edit-modes/src/lib/translate-mode.ts @@ -55,6 +55,7 @@ export class TranslateMode extends GeoJsonEditMode { return; } + event.cancelPan(); this._geometryBeforeTranslate = this.getSelectedFeaturesAsFeatureCollection(props); } diff --git a/modules/edit-modes/src/types.ts b/modules/edit-modes/src/types.ts index d9e9e2c99..8990c48e4 100644 --- a/modules/edit-modes/src/types.ts +++ b/modules/edit-modes/src/types.ts @@ -14,6 +14,7 @@ export type Pick = { index: number; object?: any; isGuide?: boolean; + featureType?: string; featureIndex?: number; type?: string; }; diff --git a/modules/edit-modes/src/utils.ts b/modules/edit-modes/src/utils.ts index eac5e0069..a6ccbcc2c 100644 --- a/modules/edit-modes/src/utils.ts +++ b/modules/edit-modes/src/utils.ts @@ -5,7 +5,7 @@ import { flattenEach } from '@turf/meta'; import { point, MultiLineString } from '@turf/helpers'; import { getCoords } from '@turf/invariant'; import WebMercatorViewport from 'viewport-mercator-project'; -import { Viewport, Pick, EditHandleFeature, EditHandleType } from './types'; +import { Viewport, Pick, EditHandleFeature, EditHandleType, StartDraggingEvent } from './types'; import { Geometry, Position, @@ -511,3 +511,7 @@ export function mapCoords( }) .filter(Boolean); } + +export function shouldCancelPan(event: StartDraggingEvent) { + return event.picks.length && event.picks.find((p) => p.featureType === 'points'); +} diff --git a/modules/layers/src/layers/editable-layer.ts b/modules/layers/src/layers/editable-layer.ts index ba0d8bc8f..b03e0dc23 100644 --- a/modules/layers/src/layers/editable-layer.ts +++ b/modules/layers/src/layers/editable-layer.ts @@ -15,6 +15,7 @@ const EVENT_TYPES = ['anyclick', 'pointermove', 'panstart', 'panmove', 'panend', export type EditableLayerProps = CompositeLayerProps & { pickingRadius?: number; pickingDepth?: number; + onCancelPan?: () => void; }; export default abstract class EditableLayer< @@ -149,7 +150,13 @@ export default abstract class EditableLayer< mapCoords, pointerDownScreenCoords: screenCoords, pointerDownMapCoords: mapCoords, - cancelPan: event.stopImmediatePropagation, + cancelPan: () => { + if (this.props.onCancelPan) { + this.props.onCancelPan(); + } + + event.stopImmediatePropagation(); + }, sourceEvent: event.srcEvent, }); }