I know that this question has been asked many times already, cause it’s the whole day I navigate through forums for a solutions, but I can’t get it to work so I’ll ask my question aswell and hope someone will be able to help me.
I have an openLayer map v5.3 with some Feature Icons, when i zoom in or out the scale with the map so eventually they overlap each other and a series of other problems.
I just want them not to scale, and so to become smaller/bigger as i zoom in/out.
This is where i define the layer:
vectorSource = new ol.source.Vector();
markerVectorLayer = new ol.layer.Vector({
source: vectorSource,
style: function(feature){
return feature.getStyle() || null;
}
});
this is my marker:
const marker = new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([mCoordinates[1], mCoordinates[0]])),
name: ocpCode,
stationTracks: ocpTracks
});
marker.setStyle(createStationStyle(code, tracks.length));
I have a null style in the layer cause anyway i give a style to each single marker, here:
function createStationStyle(markerName, nTracks) {
const spacing = 45 / (nTracks + 1);
const lines = Array.from({ length: nTracks }, (_, i) => {
const x = (i + 1) * spacing;
return `<line x1="${x}" y1="10" x2="${x}" y2="30" stroke="red" stroke-width="2"/>`;
}).join('');
return new ol.style.Style({
image: new ol.style.Icon({
src: 'data:image/svg+xml;base64,' + btoa(`
<svg xmlns="http://www.w3.org/2000/svg" width="45" height="40">
<rect x="0" y="10" width="45" height="20" fill="white" stroke="black" stroke-width="2"/>
${lines}
<text x="50%" y="7" font-size="10" text-anchor="middle" fill="black">${markerName}</text>
</svg>
`),
anchor: [0.5, 0.5]
})
});
}
I thougth about switching to Polygons cause seem easier to manage, but it would be way better to keep the icons
Thanks for any help!
1
You should use a style function to set the scale of the icon based on the inverse of the resolution. Also set the updateWhileAnimating
and updateWhileInteracting
options for the layer so the scale changes smoothly.
<html>
<head>
<style>
html, body, .map {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
</style>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ol.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/ol.css">
</head>
<body>
<div id="map" class="map"></div>
<script>
const rome = new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([12.5, 41.9])),
});
const london = new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([-0.12755, 51.507222])),
});
const madrid = new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([-3.683333, 40.4])),
});
const paris = new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([2.353, 48.8566])),
});
const berlin = new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([13.3884, 52.5169])),
});
const iconStyle = new ol.style.Style({
image: new ol.style.Icon({
src: 'https://openlayers.org/en/latest/examples/data/icon.png',
crossOrigin: '',
anchor: [0.5, 1],
}),
});
const vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [rome, london, madrid, paris, berlin],
}),
style: function(feature, resolution) {
iconStyle.getImage().setScale(10000 / resolution);
return iconStyle;
},
updateWhileAnimating: true,
updateWhileInteracting: true,
});
const rasterLayer = new ol.layer.Tile({
source: new ol.source.OSM(),
});
const map = new ol.Map({
layers: [rasterLayer, vectorLayer],
target: 'map',
view: new ol.View({
center: ol.proj.fromLonLat([2.896372, 44.6024]),
zoom: 3,
}),
});
</script>
</body>
</html>