OpenLayers has an example on how to implement snapping support for points on a map. Though I'm investigating whether snapping is also supported for moving and snapping polygons as a whole, instead of moving and snapping single points.
Though I have not found any documentation or example illustrating this. Looking in the API docs of OpenLayers, I see that Snap extends from PointerEvent, and I assume that the snapping behaviour only supports snapping at the position of the mouse pointer, which is not what I need.
Am I missing something? Or am I correct that snapping polygons as a whole currently is not supported in OpenLayers?
Use the Translate interaction as in https://openlayers.org/en/latest/examples/translate-features.html to move the polygons
const translate = new Translate({
source: vector.getSource(),
});
const snap = new Snap({
source: vector.getSource(),
});
const map = new Map({
interactions: defaultInteractions().extend([translate, snap]),
layers: [vector],
...
To snap one edge to another you need to drag the translated polygon by its edge. To avoid the Translate interaction dragging the interior of a polygon you could style fill and stroke separately and use a layer filter. Example:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v9.2.4/ol.css">
<style>
.map {
width: 100%;
height: 400px;
}
</style>
<script src="https://cdn.jsdelivr.net/npm/ol@v9.2.4/dist/ol.js"></script>
</head>
<body>
<div id="map" class="map"></div>
<script>
const vector = new ol.layer.Vector({
source: new ol.source.Vector({
url: 'https://openlayers.org/data/vector/us-states.json',
format: new ol.format.GeoJSON(),
}),
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'black',
width: 2,
}),
}),
});
const vectorFill = new ol.layer.Vector({
source: vector.getSource(),
style: new ol.style.Style({
fill: new ol.style.Fill({
color: 'red',
}),
}),
})
const translate = new ol.interaction.Translate({
source: vector.getSource(),
layers: [vector],
});
const snap = new ol.interaction.Snap({
source: vector.getSource(),
});
const map = new ol.Map({
interactions: ol.interaction.defaults.defaults().extend([translate, snap]),
layers: [vectorFill, vector],
target: 'map',
view: new ol.View({
center: ol.proj.fromLonLat([-100, 38.5]),
zoom: 4,
}),
});
</script>
</body>
</html>