TransWikia.com

Refreshing map after changing Feature's style in OpenLayers 3

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:

  1. Calling render() on the ol.Map itself.
  2. Calling dispatchChangeEvent() on the ol.source.Vector
  3. Calling 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.

3 Answers

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

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP