From ae7a731d51b7f79f0b16cc18d0ce9347fa33f147 Mon Sep 17 00:00:00 2001 From: Ben Butterworth <24711048+ben-xD@users.noreply.github.com> Date: Sun, 10 Mar 2024 21:20:00 +0000 Subject: [PATCH] feat: add DrawLineStringByDraggingMode --- docs/api-reference/modes/overview.md | 4 ++ examples/advanced/src/example.tsx | 7 ++ modules/edit-modes/src/index.ts | 1 + .../lib/draw-line-string-by-dragging-mode.ts | 72 +++++++++++++++++++ .../src/layers/editable-geojson-layer.ts | 2 + modules/main/src/index.ts | 1 + modules/react-map-gl-draw/src/index.ts | 1 + 7 files changed, 88 insertions(+) create mode 100644 modules/edit-modes/src/lib/draw-line-string-by-dragging-mode.ts diff --git a/docs/api-reference/modes/overview.md b/docs/api-reference/modes/overview.md index ee9d2f1fd..3e3691737 100644 --- a/docs/api-reference/modes/overview.md +++ b/docs/api-reference/modes/overview.md @@ -113,6 +113,10 @@ User can draw a new `Polygon` feature with 90 degree corners (right angle) by cl User can draw a new `Polygon` feature by dragging (similar to the lasso tool commonly found in photo editing software). +## [DrawLineStringByDraggingMode](https://github.com/uber/nebula.gl/blob/master/modules/edit-modes/src/lib/draw-line-string-by-dragging-mode.ts) + +User can draw a new `LineString` feature by dragging (similar to the pencil tool commonly found in sketching software). + ### ModeConfig The following options can be provided in the `modeConfig` object: diff --git a/examples/advanced/src/example.tsx b/examples/advanced/src/example.tsx index 36ad46db7..34b5f6f3b 100644 --- a/examples/advanced/src/example.tsx +++ b/examples/advanced/src/example.tsx @@ -34,6 +34,7 @@ import { DrawRectangleUsingThreePointsMode, Draw90DegreePolygonMode, DrawPolygonByDraggingMode, + DrawLineStringByDraggingMode, MeasureDistanceMode, MeasureAreaMode, MeasureAngleMode, @@ -105,6 +106,7 @@ const ALL_MODES: any = [ { label: 'Draw Polygon', mode: DrawPolygonMode }, { label: 'Draw 90° Polygon', mode: Draw90DegreePolygonMode }, { label: 'Draw Polygon By Dragging', mode: DrawPolygonByDraggingMode }, + { label: 'Draw LineString By Dragging', mode: DrawLineStringByDraggingMode }, { label: 'Draw Rectangle', mode: DrawRectangleMode }, { label: 'Draw Rectangle From Center', mode: DrawRectangleFromCenterMode }, { label: 'Draw Rectangle Using 3 Points', mode: DrawRectangleUsingThreePointsMode }, @@ -966,6 +968,11 @@ export default class Example extends React.Component< ...modeConfig, throttleMs: 100, }; + } else if (mode === DrawLineStringByDraggingMode) { + modeConfig = { + ...modeConfig, + throttleMs: 100, + }; } // Demonstrate how to override sub layer properties diff --git a/modules/edit-modes/src/index.ts b/modules/edit-modes/src/index.ts index 2a3a66251..52dc95c3c 100644 --- a/modules/edit-modes/src/index.ts +++ b/modules/edit-modes/src/index.ts @@ -36,6 +36,7 @@ export { DrawEllipseUsingThreePointsMode } from './lib/draw-ellipse-using-three- export { DrawRectangleUsingThreePointsMode } from './lib/draw-rectangle-using-three-points-mode'; export { Draw90DegreePolygonMode } from './lib/draw-90degree-polygon-mode'; export { DrawPolygonByDraggingMode } from './lib/draw-polygon-by-dragging-mode'; +export { DrawLineStringByDraggingMode } from './lib/draw-line-string-by-dragging-mode'; export { ImmutableFeatureCollection } from './lib/immutable-feature-collection'; // Other modes diff --git a/modules/edit-modes/src/lib/draw-line-string-by-dragging-mode.ts b/modules/edit-modes/src/lib/draw-line-string-by-dragging-mode.ts new file mode 100644 index 000000000..85c4aabe6 --- /dev/null +++ b/modules/edit-modes/src/lib/draw-line-string-by-dragging-mode.ts @@ -0,0 +1,72 @@ +import throttle from 'lodash.throttle'; +import { DebouncedFunc } from 'lodash'; +import { + ClickEvent, + StartDraggingEvent, + StopDraggingEvent, + DraggingEvent, + ModeProps, +} from '../types'; +import { LineString, FeatureCollection } from '../geojson-types'; +import { getPickedEditHandle } from '../utils'; +import { DrawLineStringMode } from './draw-line-string-mode'; + +type DragHandler = (event: DraggingEvent, props: ModeProps) => void; + +type ThrottledDragHandler = DebouncedFunc; + +export class DrawLineStringByDraggingMode extends DrawLineStringMode { + handleDraggingThrottled: ThrottledDragHandler | DragHandler | null | undefined = null; + + // Override the default behavior of DrawLineStringMode to not add a point when the user clicks on the map + handleClick(event: ClickEvent, props: ModeProps) { + return; + } + + handleStartDragging(event: StartDraggingEvent, props: ModeProps) { + event.cancelPan(); + if (props.modeConfig && props.modeConfig.throttleMs) { + this.handleDraggingThrottled = throttle(this.handleDraggingAux, props.modeConfig.throttleMs); + } else { + this.handleDraggingThrottled = this.handleDraggingAux; + } + } + + handleStopDragging(event: StopDraggingEvent, props: ModeProps) { + this.addClickSequence(event); + const clickSequence = this.getClickSequence(); + if (this.handleDraggingThrottled && 'cancel' in this.handleDraggingThrottled) { + this.handleDraggingThrottled.cancel(); + } + + if (clickSequence.length > 2) { + const lineStringToAdd: LineString = { + type: 'LineString', + coordinates: clickSequence, + }; + + this.resetClickSequence(); + + const editAction = this.getAddFeatureAction(lineStringToAdd, props.data); + if (editAction) { + props.onEdit(editAction); + } + } + } + + handleDraggingAux(event: DraggingEvent, props: ModeProps) { + const { picks } = event; + const clickedEditHandle = getPickedEditHandle(picks); + + if (!clickedEditHandle) { + // Don't add another point right next to an existing one. + this.addClickSequence(event); + } + } + + handleDragging(event: DraggingEvent, props: ModeProps) { + if (this.handleDraggingThrottled) { + this.handleDraggingThrottled(event, props); + } + } +} diff --git a/modules/layers/src/layers/editable-geojson-layer.ts b/modules/layers/src/layers/editable-geojson-layer.ts index d414dabf9..97b78dd06 100644 --- a/modules/layers/src/layers/editable-geojson-layer.ts +++ b/modules/layers/src/layers/editable-geojson-layer.ts @@ -26,6 +26,7 @@ import { DrawEllipseUsingThreePointsMode, Draw90DegreePolygonMode, DrawPolygonByDraggingMode, + DrawLineStringByDraggingMode, SnappableMode, TransformMode, EditAction, @@ -260,6 +261,7 @@ const modeNameMapping = { drawEllipseUsing3Points: DrawEllipseUsingThreePointsMode, draw90DegreePolygon: Draw90DegreePolygonMode, drawPolygonByDragging: DrawPolygonByDraggingMode, + drawLineStringByDragging: DrawLineStringByDraggingMode, }; // type State = { diff --git a/modules/main/src/index.ts b/modules/main/src/index.ts index ce5fd669e..44378cbcc 100644 --- a/modules/main/src/index.ts +++ b/modules/main/src/index.ts @@ -57,6 +57,7 @@ export { DrawEllipseUsingThreePointsMode } from '@nebula.gl/edit-modes'; export { DrawRectangleUsingThreePointsMode } from '@nebula.gl/edit-modes'; export { Draw90DegreePolygonMode } from '@nebula.gl/edit-modes'; export { DrawPolygonByDraggingMode } from '@nebula.gl/edit-modes'; +export { DrawLineStringByDraggingMode } from '@nebula.gl/edit-modes'; export { ImmutableFeatureCollection } from '@nebula.gl/edit-modes'; // Other modes diff --git a/modules/react-map-gl-draw/src/index.ts b/modules/react-map-gl-draw/src/index.ts index a24f3dc5e..0d82ec609 100644 --- a/modules/react-map-gl-draw/src/index.ts +++ b/modules/react-map-gl-draw/src/index.ts @@ -14,6 +14,7 @@ export { DrawPolygonMode, DrawRectangleMode, DrawPolygonByDraggingMode, + DrawLineStringByDraggingMode, MeasureDistanceMode, MeasureAreaMode, MeasureAngleMode,