I've implemented OpenLayers 6 with a Select interaction and a Draw interaction, which I toggle between.
We can assume that the user is only drawing polygons (geometry of three points or more).
I want the polygon drawn to be selected once it is completed.
So, I listen for 'drawend' on the Draw interaction, set the draw interaction to inactive, set the select interaction to active, but then I need to set the selected features to be only the drawn feature.
So far, all I have is this clunky hack that I came up with:
// Find the center point of the drawn feature (EPSG:3857)
const featureCenter: [number, number] = this._getCenterOfExtent(geometry.getExtent());
// Get the local pixel coordinate for the feature's center
const pixel: Pixel = this._map.getPixelFromCoordinate(featureCenter);
// Create a new MapBrowserEvent registering a 'click' on this local pixel coordinate
const mbEvent: MapBrowserEvent = new MapBrowserEvent('click', this._map, new MouseEvent('click', {
bubbles: true,
cancelable: true,
clientX: pixel[0],
clientY: pixel[1]
}));
// Turn off multi-polygon selection on our Select Interaction. We only want the top polygon at this spot.
this._registeredSelector.setProperties({
multi: false
});
// Trigger the 'click' event on the map
this._map.dispatchEvent(mbEvent);
Unfortunately, this doesn't always work.
I'm listening for 'click' on my Select interaction, and it does fire after forcibly triggering a click.
Sometimes, though, the event has multiple geometries of Point, LineString, and Polygon. Many times, it doesn't even have a Polygon geometry in the selected
array. Other times, it has a nearby Polygon geometry in the selected
array, and not the one we last drew.
Is there an OpenLayers native method for forcibly triggering the selection of a specific feature?
Also, here is my _getCenterOfExtent
method:
/* EXPECTS EPSG:3857 */
private _getCenterOfExtent(extent: Extent):[number, number] {
return [
extent[0] + (extent[2]-extent[0])/2,
extent[1] + (extent[3]-extent[1])/2
];
}
UPDATE
Using the screen coordinates for my click event against the window object appears to work more accurately than attempting client coordinates against the map.
Also, I found that programmatically toggling multi
on the Select Interaction does not actual work, at least not the way I was trying. I switched to always use single select, which should meet our needs.
const bbox: ClientRect | DOMRect = this._map.getTargetElement().getBoundingClientRect();
let mbEvent: MapBrowserEvent | undefined;
if (bbox) {
pixel[0] += bbox.left;
pixel[1] += bbox.top;
mbEvent = new MapBrowserEvent('click', this._map, new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true,
screenX: pixel[0],
screenY: pixel[1]
}));
} else {
mbEvent = new MapBrowserEvent('click', this._map, new MouseEvent('click', {
bubbles: true,
cancelable: true,
clientX: pixel[0],
clientY: pixel[1]
}));
}
this._map.dispatchEvent(mbEvent);