Skip to content
Merged
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
7 changes: 7 additions & 0 deletions src/components/my-map/drawing.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { FeatureLike } from "ol/Feature";
import { MultiPoint, MultiPolygon, Polygon } from "ol/geom";
import { Type } from "ol/geom/Geometry";
import { noModifierKeys, primaryAction } from "ol/events/condition";
import { Draw, Modify, Snap } from "ol/interaction";
import { Vector as VectorLayer } from "ol/layer";
import { Vector as VectorSource } from "ol/source";
Expand Down Expand Up @@ -176,6 +177,8 @@ export function configureDraw(
return new Draw({
source: drawingSource,
type: drawType,
// Reserve right-click for undoing and deleting, rather than drawing
condition: (event) => noModifierKeys(event) && primaryAction(event),
style: configureDrawInteractionStyle(drawType, drawPointer, drawColor),
});
}
Expand All @@ -185,12 +188,16 @@ export const snap = new Snap({
pixelTolerance: 15,
});

// Distance (px) from a vertex within which Modify shows the draw pointer, also used for right-click deletion
export const modifyPixelTolerance = 10;

export function configureModify(
drawPointer: DrawPointerEnum,
drawColor: string,
) {
return new Modify({
source: drawingSource,
pixelTolerance: modifyPixelTolerance,
style: new Style({
image: configureDrawPointerImage(drawPointer, drawColor),
}),
Expand Down
83 changes: 77 additions & 6 deletions src/components/my-map/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import apply from "ol-mapbox-style";
import { defaults as defaultControls, ScaleLine } from "ol/control";
import { containsCoordinate, Extent } from "ol/extent";
import { FeatureLike } from "ol/Feature";
import { altKeyOnly } from "ol/events/condition";
import { GeoJSON } from "ol/format";
import { GeoJSONFeature, GeoJSONFeatureCollection } from "ol/format/GeoJSON";
import { Geometry, Point } from "ol/geom";
Expand Down Expand Up @@ -31,6 +32,7 @@ import {
drawingSource,
DrawPointerEnum,
DrawTypeEnum,
modifyPixelTolerance,
snap,
} from "./drawing";
import pinIcon from "./icons/poi-alt.svg";
Expand Down Expand Up @@ -607,6 +609,71 @@ export class MyMap extends LitElement {
// Snap must be added after draw and modify
map.addInteraction(snap);

// Track whether a polygon is part-way through being drawn
let isDrawing = false;
draw.on("drawstart", () => (isDrawing = true));
draw.on(["drawend", "drawabort"], () => (isDrawing = false));

// Delete the point under the draw pointer, returning whether one was deleted
const deletePointAtPixel = (pixel: number[]): boolean => {
// Only delete when close enough to the point's centre for Modify to show the draw pointer
const feature = drawingSource.getClosestFeatureToCoordinate(
map.getCoordinateFromPixel(pixel),
);
const geom = feature?.getGeometry();
if (!feature || !(geom instanceof Point)) return false;
const pointPixel = map.getPixelFromCoordinate(geom.getCoordinates());
if (
Math.hypot(pointPixel[0] - pixel[0], pointPixel[1] - pixel[1]) >
modifyPixelTolerance
)
return false;

drawingSource.removeFeature(feature);

// Re-number remaining labels so the next drawn point doesn't duplicate an existing label
drawingSource
.getFeatures()
.forEach((sketch, i) => sketch.set("label", `${i + 1}`));

// The 'change' listener below only dispatches when features remain
if (drawingSource.getFeatures().length === 0) {
this.dispatch("geojsonChange", {});

// If limited to a single point, allow drawing again (snap must be added after draw)
if (!this.drawMany) {
map.removeInteraction(snap);
map.addInteraction(draw);
map.addInteraction(snap);
}
}
return true;
};

// Right-click to undo the last vertex while drawing, or delete the point/vertex under the draw pointer
map.getViewport().addEventListener("contextmenu", (event) => {
if (isDrawing) {
event.preventDefault();
draw.removeLastPoint();
return;
}

const pixel = map.getEventPixel(event);
const deleted =
this.drawType === "Point"
? deletePointAtPixel(pixel)
: // Modify only removes a vertex within its pixelTolerance, and won't reduce a polygon below a triangle
modify.removePoint(map.getCoordinateFromPixel(pixel));
if (deleted) event.preventDefault();
});

// Alt-click (Option-click on Mac) to delete a point, matching Modify's built-in vertex deletion for polygons
if (this.drawType === "Point") {
map.on("singleclick", (event) => {
if (altKeyOnly(event)) deletePointAtPixel(event.pixel);
});
}

// 'change' listens for 'drawend' and modifications
drawingSource.on("change", () => {
const sketches = drawingSource.getFeatures();
Expand Down Expand Up @@ -905,9 +972,11 @@ export class MyMap extends LitElement {
<div
id="${this.id}"
class="map"
role="${this.staticMode && !this.collapseAttributions
? "presentation"
: "application"}"
role="${
this.staticMode && !this.collapseAttributions
? "presentation"
: "application"
}"
tabindex="${this.staticMode && !this.collapseAttributions ? -1 : 0}"
data-testid="${this.dataTestId}"
/>`
Expand All @@ -918,9 +987,11 @@ export class MyMap extends LitElement {
<div
id="${this.id}"
class="map"
role="${this.staticMode && !this.collapseAttributions
? "presentation"
: "application"}"
role="${
this.staticMode && !this.collapseAttributions
? "presentation"
: "application"
}"
tabindex="${this.staticMode && !this.collapseAttributions ? -1 : 0}"
data-testid="${this.dataTestId}"
/>`;
Expand Down
Loading