Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion docs/api-reference/modes/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,14 @@ The following options can be provided in the `modeConfig` object:

## [ResizeCircleMode](https://github.com/uber/nebula.gl/blob/master/modules/edit-modes/src/lib/resize-circle-mode.js)

User can resize an existing circular Polygon feature by clicking and dragging along the ring.
User can resize an existing circular Polygon feature by clicking along the ring.

### ModeConfig

The following options can be provided in the `modeConfig` object:

- `dragToDraw` (optional): `boolean`
- If `true`, user can click and drag instead of clicking twice. Note however, that the user will not be able to pan the map while drawing.

## [DrawPolygonMode](https://github.com/uber/nebula.gl/blob/master/modules/edit-modes/src/lib/draw-polygon-mode.js)

Expand Down
3 changes: 3 additions & 0 deletions examples/advanced/src/example.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,9 @@ export default class Example extends React.Component<
if (this.state.mode === MeasureDistanceMode) {
controls.push(this._renderMeasureDistanceControls());
}
if (this.state.mode === ResizeCircleMode) {
controls.push(this._renderTwoClickPolygonControls());
}
if (this.state.mode === DrawPolygonMode) {
controls.push(this._renderDrawPolygonModeControls());
}
Expand Down
91 changes: 64 additions & 27 deletions modules/edit-modes/src/lib/resize-circle-mode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import {
getPickedEditHandle,
NearestPointType,
} from '../utils';
import { LineString, Point, FeatureCollection, FeatureOf } from '../geojson-types';
import { LineString, Point, Position, FeatureCollection, FeatureOf } from '../geojson-types';
import {
ClickEvent,
ModeProps,
PointerMoveEvent,
StartDraggingEvent,
Expand Down Expand Up @@ -128,39 +129,46 @@ export class ResizeCircleMode extends GeoJsonEditMode {
}

handleDragging(event: DraggingEvent, props: ModeProps<FeatureCollection>): void {
if (props.modeConfig && !props.modeConfig.dragToDraw) {
return;
}

const editHandle = getPickedEditHandle(event.pointerDownPicks);

if (editHandle) {
// Cancel map panning if pointer went down on an edit handle
event.cancelPan();

const editHandleProperties = editHandle.properties;
const featureIndex = editHandleProperties.featureIndex;
const pointerPosition = event.mapCoords;
this.drawCircle(featureIndex, pointerPosition, props);
}
}

handleClick(event: ClickEvent, props: ModeProps<FeatureCollection>) {
if (props.modeConfig && props.modeConfig.dragToDraw) {
// handled in drag handlers
return;
}

const feature = this.getSelectedFeature(props);
const center = turfCenter(feature).geometry.coordinates;
const numberOfSteps = Object.entries(feature.geometry.coordinates[0]).length - 1;
const radius = Math.max(distance(center, event.mapCoords), 0.001);

const { steps = numberOfSteps } = {};
const options = { steps };
const updatedFeature = circle(center, radius, options);
const geometry = updatedFeature.geometry;

const updatedData = new ImmutableFeatureCollection(props.data)
.replaceGeometry(editHandleProperties.featureIndex, geometry)
.getObject();

props.onEdit({
updatedData,
editType: 'unionGeometry',
editContext: {
featureIndexes: [editHandleProperties.featureIndex],
},
});
this.addClickSequence(event);
const clickSequence = this.getClickSequence();
if (clickSequence.length > 1) {
this._isResizing = false;
this.resetClickSequence();
} else {
this._isResizing = true;
}
}

handlePointerMove(event: PointerMoveEvent, props: ModeProps<FeatureCollection>): void {
if (props.modeConfig && !props.modeConfig.dragToDraw && this._isResizing) {
const featureIndex = props.selectedIndexes[0];
const pointerPosition = event.mapCoords;
this.drawCircle(featureIndex, pointerPosition, props);
}

if (!this._isResizing) {
const selectedEditHandle = getPickedEditHandle(event.picks);
this._selectedEditHandle =
Expand All @@ -169,30 +177,59 @@ export class ResizeCircleMode extends GeoJsonEditMode {
: null;
}

const cursor = this.getCursor(event);
const cursor = this.getCursor(event, props);
props.onUpdateCursor(cursor);
}

handleStartDragging(event: StartDraggingEvent, props: ModeProps<FeatureCollection>) {
if (this._selectedEditHandle) {
if (props.modeConfig && props.modeConfig.dragToDraw && this._selectedEditHandle) {
this._isResizing = true;
}
}

handleStopDragging(event: StopDraggingEvent, props: ModeProps<FeatureCollection>) {
if (this._isResizing) {
if (props.modeConfig && props.modeConfig.dragToDraw && this._isResizing) {
this._selectedEditHandle = null;
this._isResizing = false;
}
}

getCursor(event: PointerMoveEvent): string | null | undefined {
getCursor(
event: PointerMoveEvent,
props: ModeProps<FeatureCollection>
): string | null | undefined {
const picks = (event && event.picks) || [];

const handlesPicked = getPickedEditHandles(picks);
if (handlesPicked.length) {
const isResizingByClickingTwice =
props.modeConfig && !props.modeConfig.dragToDraw && this._isResizing;
if (handlesPicked.length || isResizingByClickingTwice) {
return 'cell';
}
return null;
}

drawCircle(featureIndex: number, pointerPosition: Position, props: ModeProps<FeatureCollection>) {
const feature = this.getSelectedFeature(props);
const center = turfCenter(feature).geometry.coordinates;
const numberOfSteps = Object.entries(feature.geometry.coordinates[0]).length - 1;
const radius = Math.max(distance(center, pointerPosition), 0.001);

const { steps = numberOfSteps } = {};
const options = { steps };
const updatedFeature = circle(center, radius, options);
const geometry = updatedFeature.geometry;

const updatedData = new ImmutableFeatureCollection(props.data)
.replaceGeometry(featureIndex, geometry)
.getObject();

props.onEdit({
updatedData,
editType: 'unionGeometry',
editContext: {
featureIndexes: [featureIndex],
},
});
}
}