Geographic Information Systems Asked by Xharlie on November 28, 2020
I have an OpenLayers 3.2.0 map that features some vector sources (ol.source.Vector
) and associated vector layers (ol.layer.Vector
)
When Features (ol.Feature
) are added to the vector sources, they are given a data
property that is set to the javascript object that the feature represents. TypeScript follows…
vectorSource.addFeature(new ol.Feature({
geometry: /* ... */,
data: vectorData,
}));
The vector layers then have a style-function that reads the data
property and retrieves its style:
vectorLayer = new ol.layer.Vector({
source: vectorSource,
renderBuffer: /* ... */,
style: function (feature: ol.Feature, resolution: any) {
var data = </* TypeScript Type */>feature.get('data');
if ((data) && (data.style)) {
return [data.style];
}
else {
/* return default style */
}
}
});
Sometimes, events unrelated to the map cause the styles to change. For example, when an object becomes invalid, its style changes. Clearly, since data.style
is entirely within my control, changing it is trivial.
The problem is that the map does not know that the style has changed. If I change an object’s style and then zoom the map, forcing it to redraw, I notice that my style-functions run and return the new style and the feature is redrawn. How do I programatically force the map to refresh?
After some searching and experimentation, I have tried:
render()
on the ol.Map
itself.dispatchChangeEvent()
on the ol.source.Vector
redraw()
on the ol.layer.Vector
These were suggested but none of them worked, which isn’t surprising since only the first method is even listed in the OpenLayers 3.2.0 API documentation and it is not marked as stable.
By chance, I have stumbled upon the answer - it is to call changed()
on the features themselves after changing the style
property of their associated data. See: http://openlayers.org/en/v3.2.0/apidoc/ol.Feature.html?unstable=true#changed
This does require me to keep track of the ol.Feature
objects associated with each vectorData
object (formerly, I only ever needed to find the vectorData
from a feature, which could be done with get()
) but this isn't much of a cost.
(I found this by looking at setGeometry
and setStyle
and other methods on ol.Feature
to see what they do.)
Correct answer by Xharlie on November 28, 2020
I spent a week on trying to figure out how to make a feature (Polygon) disappear from the map after deleting it (vectorSource.removeFeature(selectedFeature)
. And no solution worked. Oddly the current OL3 v3.15.1 doesn't have basic forced-refresh/render function that works! The solution that worked for me was to change selectedFeature
's style:
var newStyle = new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({color: 'red'}),
stroke: new ol.style.Stroke({color: 'yellow', width: 1})
})
});
selectedFeature.setStyle(newStyle)
Any style would work since the feature has already been removed from the layer but not refreshed.
Answered by Morey on November 28, 2020
Xharlie's answer helped me with the calling changed idea, except that in some cases you have to call it on the layer instead of the feature. In my case I had a style function bound to the layer and the style used a calculated geometry instead of the geometry of the feature.
layer.changed()
map.once('rendercomplete', () => {
layer.changed()
})
map.renderSync()
ps: I actually do all this once more inside the first rendercomplete listener; and disable user interaction during this time; not ideal especially when it's long to compute so if you can avoid this kind of hack all the best for you.
Answered by Rivenfall on November 28, 2020
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP