When I select one of the squares, I need to be able to bring that feature to the front. If I don't bring it to the front, it looks like:
and the right edge of the square is hidden behind the square to the right.
I did find one possible solution which was to use:
const tmp = e.selected[0].clone();
vectorLayer.getSource().removeFeature(e.selected[0]);
vectorLayer.getSource().addFeature(tmp);
which removes the selected feature and adds it back in. When added back in, it is in front of everything else. This works when I select one of the squares, but fails when I select the second. Selecting the second should set the first back to the deselected state, but that no longer happens. It looks like:
What do I need to change so that I can show one of the squares as selected and in front?
const squares = {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
[40, 20],
[40, 30],
[50, 30],
[50, 20]
]
]
}
},
{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
[50, 20],
[50, 30],
[60, 30],
[60, 20]
]
]
}
},
{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
[60, 20],
[60, 30],
[70, 30],
[70, 20]
]
]
}
}
]
};
const styles = {
Polygon: new ol.style.Style({
stroke: new ol.style.Stroke({
color: "hsla(0, 50%, 100%, 1.0)",
width: 5
}),
fill: new ol.style.Fill({
color: "hsla(0, 50%, 50%, 0.3)"
})
})
};
const styleFunction = function (feature) {
const featureType = feature.getGeometry().getType();
return styles[featureType];
};
const vectorSource = new ol.source.Vector({
features: new ol.format.GeoJSON({
featureProjection: "EPSG:4326" // 4326 3857
}).readFeatures(squares)
});
const vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: styleFunction
});
const map = new ol.Map({
target: "map",
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vectorLayer
],
view: new ol.View({
projection: "EPSG:4326",
center: [60, 20],
zoom: 5
})
});
const selected = new ol.style.Style({
fill: new ol.style.Fill({
color: "hsla(270, 50%, 50%, .1)"
}),
stroke: new ol.style.Stroke({
color: "hsla(270, 50%, 50%, 1)",
width: 5
})
});
function selectStyle(feature) {
const color = feature.get("COLOR") || "hsla(270, 50%, 50%, .1)";
selected.getFill().setColor(color);
return selected;
}
const selectSingleClick = new ol.interaction.Select({ style: selectStyle });
selectSingleClick.on("select", function (e) {
if (e.selected.length > 0) {
console.log("select event");
const tmp = e.selected[0].clone();
vectorLayer.getSource().removeFeature(e.selected[0]);
vectorLayer.getSource().addFeature(tmp);
}
});
map.addInteraction(selectSingleClick);
#map {
height: 450px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.1.0/ol.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.1.0/dist/ol.min.js"></script>
<div id="map"></div>
The selected
style should have a zIndex value higher than that of the unselected style used for the layer. Default is 0 so anything higher will work.
const squares = {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
[40, 20],
[40, 30],
[50, 30],
[50, 20]
]
]
}
},
{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
[50, 20],
[50, 30],
[60, 30],
[60, 20]
]
]
}
},
{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
[60, 20],
[60, 30],
[70, 30],
[70, 20]
]
]
}
}
]
};
const styles = {
Polygon: new ol.style.Style({
stroke: new ol.style.Stroke({
color: "hsla(0, 50%, 100%, 1.0)",
width: 5
}),
fill: new ol.style.Fill({
color: "hsla(0, 50%, 50%, 0.3)"
})
})
};
const styleFunction = function (feature) {
const featureType = feature.getGeometry().getType();
return styles[featureType];
};
const vectorSource = new ol.source.Vector({
features: new ol.format.GeoJSON({
featureProjection: "EPSG:4326" // 4326 3857
}).readFeatures(squares)
});
const vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: styleFunction
});
const map = new ol.Map({
target: "map",
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vectorLayer
],
view: new ol.View({
projection: "EPSG:4326",
center: [60, 20],
zoom: 5
})
});
const selected = new ol.style.Style({
fill: new ol.style.Fill({
color: "hsla(270, 50%, 50%, .1)"
}),
stroke: new ol.style.Stroke({
color: "hsla(270, 50%, 50%, 1)",
width: 5
}),
zIndex: 1
});
function selectStyle(feature) {
const color = feature.get("COLOR") || "hsla(270, 50%, 50%, .1)";
selected.getFill().setColor(color);
return selected;
}
const selectSingleClick = new ol.interaction.Select({ style: selectStyle });
map.addInteraction(selectSingleClick);
#map {
height: 450px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.1.0/ol.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.1.0/dist/ol.min.js"></script>
<div id="map"></div>