https://openlayers.org/en/latest/examples/draw-and-modify-geodesic.html Here as the example are those circles [enter image description here] (https://i.sstatic.net/6HPGpZMB.png) and in the example of the website allows to drag from the border to modify the size of the circle I have been a few days to replicate this feature but i am not able to do it here you can check the website example : import Map from 'ol/Map.js'; import View from 'ol/View.js'; import {Circle as CircleStyle, Fill, Stroke, Style} from 'ol/style.js'; import {Draw, Modify, Snap} from 'ol/interaction.js'; import {GeometryCollection, Point, Polygon} from 'ol/geom.js'; import {OSM, Vector as VectorSource} from 'ol/source.js'; import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer.js'; import {circular} from 'ol/geom/Polygon.js'; import {getDistance} from 'ol/sphere.js'; import {transform} from 'ol/proj.js'; const raster = new TileLayer({ source: new OSM(), }); const source = new VectorSource(); const style = new Style({ fill: new Fill({ color: 'rgba(255, 255, 255, 0.2)', }), stroke: new Stroke({ color: '#33cc33', width: 2, }), image: new CircleStyle({ radius: 7, fill: new Fill({ color: '#ffcc33', }), }), }); const geodesicStyle = new Style({ geometry: function (feature) { return feature.get('modifyGeometry') || feature.getGeometry(); }, fill: new Fill({ color: 'rgba(255, 255, 255, 0.2)', }), stroke: new Stroke({ color: '#ff3333', width: 2, }), image: new CircleStyle({ radius: 7, fill: new Fill({ color: 'rgba(0, 0, 0, 0)', }), }), }); const vector = new VectorLayer({ source: source, style: function (feature) { const geometry = feature.getGeometry(); return geometry.getType() === 'GeometryCollection' ? geodesicStyle : style; }, }); const map = new Map({ layers: [raster, vector], target: 'map', view: new View({ center: [-11000000, 6600000], zoom: 3, }), }); const defaultStyle = new Modify({source: source}) .getOverlay() .getStyleFunction(); const modify = new Modify({ source: source, style: function (feature) { feature.get('features').forEach(function (modifyFeature) { const modifyGeometry = modifyFeature.get('modifyGeometry'); if (modifyGeometry) { const modifyPoint = feature.getGeometry().getCoordinates(); const geometries = modifyFeature.getGeometry().getGeometries(); const polygon = geometries[0].getCoordinates()[0]; const center = geometries[1].getCoordinates(); const projection = map.getView().getProjection(); let first, last, radius; if (modifyPoint[0] === center[0] && modifyPoint[1] === center[1]) { // center is being modified // get unchanged radius from diameter between polygon vertices first = transform(polygon[0], projection, 'EPSG:4326'); last = transform( polygon[(polygon.length - 1) / 2], projection, 'EPSG:4326', ); radius = getDistance(first, last) / 2; } else { // radius is being modified first = transform(center, projection, 'EPSG:4326'); last = transform(modifyPoint, projection, 'EPSG:4326'); radius = getDistance(first, last); } // update the polygon using new center or radius const circle = circular( transform(center, projection, 'EPSG:4326'), radius, 128, ); circle.transform('EPSG:4326', projection); geometries[0].setCoordinates(circle.getCoordinates()); // save changes to be applied at the end of the interaction modifyGeometry.setGeometries(geometries); } }); return defaultStyle(feature); }, }); modify.on('modifystart', function (event) { event.features.forEach(function (feature) { const geometry = feature.getGeometry(); if (geometry.getType() === 'GeometryCollection') { feature.set('modifyGeometry', geometry.clone(), true); } }); }); modify.on('modifyend', function (event) { event.features.forEach(function (feature) { const modifyGeometry = feature.get('modifyGeometry'); if (modifyGeometry) { feature.setGeometry(modifyGeometry); feature.unset('modifyGeometry', true); } }); }); map.addInteraction(modify); let draw, snap; // global so we can remove them later const typeSelect = document.getElementById('type'); function addInteractions() { let value = typeSelect.value; let geometryFunction; if (value === 'Geodesic') { value = 'Circle'; geometryFunction = function (coordinates, geometry, projection) { if (!geometry) { geometry = new GeometryCollection([ new Polygon([]), new Point(coordinates[0]), ]); } const geometries = geometry.getGeometries(); const center = transform(coordinates[0], projection, 'EPSG:4326'); const last = transform(coordinates[1], projection, 'EPSG:4326'); const radius = getDistance(center, last); const circle = circular(center, radius, 128); circle.transform('EPSG:4326', projection); geometries[0].setCoordinates(circle.getCoordinates()); geometry.setGeometries(geometries); return geometry; }; } draw = new Draw({ source: source, type: value, geometryFunction: geometryFunction, }); map.addInteraction(draw); snap = new Snap({source: source}); map.addInteraction(snap); } /** * Handle change event. */ typeSelect.onchange = function () { map.removeInteraction(draw); map.removeInteraction(snap); addInteractions(); }; addInteractions(); But i been trying to replicate it and i keep getting this : enter image description here I have been stuck to make it work in my component , for a few days already This is the code i am working with ngAfterViewInit(): void { if (!this.map) { this.initializeMap(); this.addInteractions(); this.updateCircles(this.latitude, this.longitude, this.radius); } } initializeMap(): void { const raster = new TileLayer({ source: new OSM(), }); this.vector = new VectorLayer({ source: this.source, style: () => this.geodesicStyle(), }); this.map = new Map({ layers: [raster, this.vector], target: this.mapContainer.nativeElement, view: new View({ center: fromLonLat([10.0, 50.0]), // Central Europe zoom: 4, // Adjust the zoom level }), }); const translate = new Translate({ layers: [this.vector] }); const modify = new Modify({ source: this.source, style: this.geodesicStyle() }); modify.on('modifyend', (event) => { const features = this.source.getFeatures(); if (features.length > 0) { const geometry = features[0].getGeometry() as GeometryCollection; if (!geometry) return; const geometries = geometry.getGeometries(); const center = (geometries[1] as Point).getCoordinates(); const edge = (geometries[0] as Polygon).getCoordinates()[0][0]; const projection = this.map.getView().getProjection(); const centerCoords = transform(center, projection, 'EPSG:4326'); const edgeCoords = transform(edge, projection, 'EPSG:4326'); this.longitude = centerCoords[0]; this.latitude = centerCoords[1]; this.radius = getDistance(centerCoords, edgeCoords); const newCircle = circular([this.longitude, this.latitude], this.radius, 128); newCircle.transform('EPSG:4326', 'EPSG:3857'); geometries[0] = newCircle; geometry.setGeometries(geometries); this.emitCoordinatesChange(); } }); translate.on('translateend', (event) => { const features = this.source.getFeatures(); if (features.length > 0) { const geometry = features[0].getGeometry() as GeometryCollection; if (!geometry) return; const geometries = geometry.getGeometries(); const center = (geometries[1] as Point).getCoordinates(); const edge = (geometries[0] as Polygon).getCoordinates()[0][0]; const projection = this.map.getView().getProjection(); const centerCoords = transform(center, projection, 'EPSG:4326'); const edgeCoords = transform(edge, projection, 'EPSG:4326'); this.longitude = centerCoords[0]; this.latitude = centerCoords[1]; this.radius = getDistance(centerCoords, edgeCoords); this.emitCoordinatesChange(); } }); this.source.on('change', (event) => { const features = this.source.getFeatures(); if (features.length > 0) { const geometry = features[0].getGeometry() as GeometryCollection; if (!geometry) return; const geometries = geometry.getGeometries(); const center = (geometries[1] as Point).getCoordinates(); const edge = (geometries[0] as Polygon).getCoordinates()[0][0]; const projection = this.map.getView().getProjection(); const centerCoords = transform(center, projection, 'EPSG:4326'); const edgeCoords = transform(edge, projection, 'EPSG:4326'); this.longitude = centerCoords[0]; this.latitude = centerCoords[1]; this.radius = getDistance(centerCoords, edgeCoords); this.emitCoordinatesChange(); } }); this.map.addInteraction(modify); this.map.addInteraction(translate); } calculateRadius(polygon: Polygon): number { const coordinates = polygon.getCoordinates()[0]; const first = coordinates[0]; const last = coordinates[Math.floor(coordinates.length / 2)]; const center = transform(first, 'EPSG:3857', 'EPSG:4326'); const edge = transform(last, 'EPSG:3857', 'EPSG:4326'); return getDistance(center, edge); } addInteractions(): void { let geometryFunction = (coordinates: any, geometry: any) => { if (!geometry) { geometry = new GeometryCollection([new Polygon([]), new Point(coordinates[0])]); } const geometries = geometry.getGeometries(); const center = transform(coordinates[0], 'EPSG:3857', 'EPSG:4326'); const last = transform(coordinates[1], 'EPSG:3857', 'EPSG:4326'); const radius = getDistance(center, last); const circle = circular(center, radius, 128); circle.transform('EPSG:4326', 'EPSG:3857'); geometries[0].setCoordinates(circle.getCoordinates()); geometries[1].setCoordinates(coordinates[0]); geometry.setGeometries(geometries); return geometry; }; this.draw = new Draw({ source: this.source, type: 'Circle', geometryFunction: geometryFunction, }); this.draw.on('drawstart', () => { this.source.clear(); }); this.modify = new Modify({ source: this.source, style: this.geodesicStyle(), insertVertexCondition: () => true }); this.modify.on('modifyend', (event) => { const features = this.source.getFeatures(); if (features.length > 0) { const geometry = features[0].getGeometry() as GeometryCollection; if (!geometry) return; const geometries = geometry.getGeometries(); const center = (geometries[1] as Point).getCoordinates(); const edge = (geometries[0] as Polygon).getCoordinates()[0][0]; const projection = this.map.getView().getProjection(); const centerCoords = transform(center, projection, 'EPSG:4326'); const edgeCoords = transform(edge, projection, 'EPSG:4326'); this.longitude = centerCoords[0]; this.latitude = centerCoords[1]; this.radius = getDistance(centerCoords, edgeCoords); const newCircle = circular([this.longitude, this.latitude], this.radius, 128); newCircle.transform('EPSG:4326', 'EPSG:3857'); geometries[0] = newCircle; geometry.setGeometries(geometries); this.emitCoordinatesChange(); } }); this.map.addInteraction(this.draw); this.map.addInteraction(this.modify); this.snap = new Snap({ source: this.source }); this.map.addInteraction(this.snap); } emitCoordinates(feature: any): void { const geometry = feature.getGeometry() as GeometryCollection; const geometries = geometry.getGeometries(); const center = transform((geometries[1] as Point).getCoordinates(), 'EPSG:3857', 'EPSG:4326'); const edge = transform((geometries[0] as Polygon).getCoordinates()[0][0], 'EPSG:3857', 'EPSG:4326'); const radius = getDistance(center, edge); this.coordinatesChange.emit({ latitude: center[1], longitude: center[0], radius: radius, }); } geodesicStyle() { return new Style({ fill: new Fill({ color: 'rgba(255, 255, 255, 0.2)', }), stroke: new Stroke({ color: '#ff3333', width: 2, }), image: new CircleStyle({ radius: 7, fill: new Fill({ color: 'rgba(0, 0, 0, 0)', }), }), }); } modifyStyle(feature: any) { return this.geodesicStyle(); } onTypeChange(event: any): void { const selectedType = event.target.value; this.map.removeInteraction(this.draw); this.map.removeInteraction(this.snap); let geometryFunction = (coordinates: any, geometry: any) => { if (!geometry) { geometry = new GeometryCollection([new Polygon([]), new Point(coordinates[0])]); } const geometries = geometry.getGeometries(); const center = transform(coordinates[0], 'EPSG:3857', 'EPSG:4326'); const last = transform(coordinates[1], 'EPSG:3857', 'EPSG:4326'); const radius = getDistance(center, last); const circle = circular(center, radius, 128); circle.transform('EPSG:4326', 'EPSG:3857'); geometries[0].setCoordinates(circle.getCoordinates()); geometries[1].setCoordinates(coordinates[0]); // Correctly set center as a point geometry.setGeometries(geometries); return geometry; }; this.draw = new Draw({ source: this.source, type: 'Circle', geometryFunction: geometryFunction, }); this.map.addInteraction(this.draw); this.snap = new Snap({ source: this.source }); this.map.addInteraction(this.snap); } addMapClickListener(): void { this.map.on('click', (event) => { const clickedCoord = this.map.getCoordinateFromPixel(event.pixel); const lonLat = transform(clickedCoord, 'EPSG:3857', 'EPSG:4326'); this.longitude = lonLat[0]; this.latitude = lonLat[1]; this.radius = this.radius || 1000; this.updateCircles(this.latitude, this.longitude, this.radius); }); } updateCircles(latitude: number, longitude: number, radius: number): void { this.source.clear(); const validRadius = radius || 100000; this.latitude = latitude; this.longitude = longitude; this.radius = validRadius; const circle = circular([this.longitude, this.latitude], validRadius, 128); circle.transform('EPSG:4326', 'EPSG:3857'); const center = fromLonLat([this.longitude, this.latitude]); const point = new Point(center); const geometryCollection = new GeometryCollection([ circle, point ]); const feature = new Feature({ geometry: geometryCollection }); this.source.addFeature(feature); const zoomLevel = Math.max(1, Math.min(16, Math.floor(16 - Math.log(radius / 1000) / Math.LN2))); this.map.getView().setCenter(center); this.map.getView().setZoom(zoomLevel); } private emitCoordinatesChange(): void { this.coordinatesChange.emit({ latitude: this.latitude, longitude: this.longitude, radius: this.radius }); } }``` I assume the error or the duplication it may be between the draw feature or with the updates but i dont know what to check anymore Continue reading...