Draw Shapes
See https://openlayers.org/en/latest/examples/draw-shapes.html
import React, { useState } from "react";
import "ol/ol.css";
import {
createBox,
createRegularPolygon,
GeometryFunction,
} from "ol/interaction/Draw";
import OlSourceVector from "ol/source/Vector";
import Polygon from "ol/geom/Polygon";
import GeometryType from "ol/geom/GeometryType";
import { Geometry } from "ol/geom";
import { Map } from "@react-ol/fiber";
export function useGeometryFunction(shapeType) {
if (["None", "Circle"].includes(shapeType)) {
return;
}
if (shapeType === "Square") {
return createRegularPolygon(4);
}
if (shapeType === "Box") {
return createBox();
}
if (shapeType === "Star") {
return (coordinates, geometry) => {
const center = coordinates[0];
const last = coordinates[1];
const dx = center[0] - last[0];
const dy = center[1] - last[1];
const radius = Math.sqrt(dx * dx + dy * dy);
const rotation = Math.atan2(dy, dx);
const newCoordinates = [];
const numPoints = 12;
for (let i = 0; i < numPoints; i += 1) {
const angle = rotation + (i * 2 * Math.PI) / numPoints;
const fraction = i % 2 === 0 ? 1 : 0.5;
const offsetX = radius * fraction * Math.cos(angle);
const offsetY = radius * fraction * Math.sin(angle);
newCoordinates.push([center[0] + offsetX, center[1] + offsetY]);
}
newCoordinates.push(newCoordinates[0].slice());
if (!geometry) {
geometry = new Polygon([newCoordinates]);
} else {
geometry.setCoordinates([newCoordinates]);
}
return geometry;
};
}
}
export const ExampleDrawShapes = () => {
const [shapeType, setShapeType] = useState("Circle");
const geometryFunction = useGeometryFunction(shapeType);
const [vectorSource, setVectorSource] = useState();
return (
<>
<form>
<label htmlFor="type">Geometry type:</label>
<select
id="type"
value={shapeType}
onChange={(e) => setShapeType(e.target.value)}
>
<option value="Circle">Circle</option>
<option value="Square">Square</option>
<option value="Box">Box</option>
<option value="Star">Star</option>
<option value="None">None</option>
</select>
</form>
<Map>
<olView initialCenter={[-11000000, 4600000]} initialZoom={4} />
<olLayerTile>
<olSourceOSM />
</olLayerTile>
<olLayerVector>
<olSourceVector ref={setVectorSource} />
</olLayerVector>
{vectorSource && shapeType !== "None" ? (
<olInteractionDraw
args={{
source: vectorSource,
type: GeometryType.CIRCLE,
geometryFunction,
}}
/>
) : null}
</Map>
</>
);
};