0

I am working with Openlayers version 7 and I have A vectorLayer with a style function to be applied on each feature, a modify interaction with no style set that takes a selected feature to be modified, and a select interaction with a style function. I've noticed that everytime I select a feature and start modifying it, a change event fires to the vectorlayer and that last one execute the style function for each unselected feature exist in that vectorlayer. I'm wondering if there is any solution stop the vectorlayer from executing on every change for every feature. I am modifying only the selected feature, I see unecessary to run the stylefunction on the vectorlayer for all unselected features

<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>Document</title>
        <link rel="stylesheet" href="./libs/v6.0.0-dist/ol.css" />
        <link rel="stylesheet" href="./styles.css" />
    </head>
    <body>
        <div id="js-map" class="map"></div>
        <script src="./libs/v6.0.0-dist/ol.js"></script>
        <script src="https://unpkg.com/@turf/turf@6/turf.min.js"></script>
        <script>
            window.onload = init;
            function init() {
                const map = new ol.Map({
                    view: new ol.View({
                        center: [-12080385, 7567433],
                        zoom: 3,
                        maxZoom: 6,
                        minZoom: 2,
                    }),
                    layers: [
                        new ol.layer.Tile({
                            source: new ol.source.OSM(),
                        }),
                    ],
                    target: 'js-map',
                    keyboardEventTarget: document,
                });

                const vectorSource = new ol.source.Vector();
                const vectoreLayer = new ol.layer.Vector({
                    source: vectorSource,
                    style: (feature) => {
                        console.log('vectorStyle');
                        if (feature.getGeometry().getType() === 'LineString') {
                            return [
                                new ol.style.Style({
                                    stroke: new ol.style.Stroke({
                                        color: '#ff0000',
                                    }),
                                }),
                            ];
                        }
                    },
                });
                map.addLayer(vectoreLayer);
                const drawInteraction = new ol.interaction.Draw({
                    source: vectorSource,
                    type: 'LineString',
                });
                map.addInteraction(drawInteraction);

                const selecInteraction = new ol.interaction.Select({
                    layers: [vectoreLayer],
                    hitTolerance: 10,
                    style: (feature) => {
                        console.log('selectStyle');
                        if (feature.getGeometry().getType() === 'LineString') {
                            return [
                                new ol.style.Style({
                                    stroke: new ol.style.Stroke({
                                        color: '#ff0000',
                                    }),
                                }),
                                new ol.style.Style({
                                    image: new ol.style.Circle({
                                        radius: 5,
                                        fill: new ol.style.Fill({
                                            color: '#f59e0b',
                                        }),
                                        stroke: new ol.style.Stroke({
                                            color: '#000000',
                                            width: 2,
                                        }),
                                    }),
                                    geometry: function () {
                                        const coordinates = feature.getGeometry().getCoordinates();
                                        return new ol.geom.MultiPoint(coordinates);
                                    },
                                }),
                            ];
                        }
                    },
                });

                map.on('contextmenu', () => {
                    map.removeInteraction(drawInteraction);
                });
                map.addInteraction(selecInteraction);
                map.addInteraction(
                    new ol.interaction.Modify({
                        features: selecInteraction.getFeatures(),
                        pixelTolerance: 10,
                    })
                );
            }
        </script>
    </body>
</html>


BinaryHawk
  • 45
  • 6

1 Answers1

0

It is normal for style functions to be called for each render cycle (that happens even with the default styles, and with complex vector tile layers) but they do not need to construct new styles on each call:

const lineStyle = new ol.style.Style({
    stroke: new ol.style.Stroke({
        color: '#ff0000',
    }),
});

const vertexStyle = new ol.style.Style({
    image: new ol.style.Circle({
        radius: 5,
        fill: new ol.style.Fill({
            color: '#f59e0b',
        }),
        stroke: new ol.style.Stroke({
            color: '#000000',
            width: 2,
        }),
    }),
    geometry: function () {
        const coordinates = feature.getGeometry().getCoordinates();
        return new ol.geom.MultiPoint(coordinates);
    },
});

const vectoreLayer = new ol.layer.Vector({
    source: vectorSource,
    style: (feature) => {
        if (feature.getGeometry().getType() === 'LineString') {
            return lineStyle;
        }
    },
});

const selecInteraction = new ol.interaction.Select({
    layers: [vectoreLayer],
    hitTolerance: 10,
    style: (feature) => {
        if (feature.getGeometry().getType() === 'LineString') {
            return [
                lineStyle,
                verrtexStyle,
            ];
        }
    },
});
Mike
  • 16,042
  • 2
  • 14
  • 30
  • Isn't that gonna decrease the performance of the appplication ? if I have 50 features on the VectorLayer, modifying one feature will run the selectStyleFunction for that feature and another 49 vectorlayerStyleFunction, isn't it possible to make run only the selectStyleFunction and when modify ends apply those changes to the vectorlayer – BinaryHawk Nov 15 '22 at 10:34
  • The whole map is re-rendered for any change. The only extra overhead over the default style is testing `(feature.getGeometry().getType() === 'LineString')`. – Mike Nov 15 '22 at 14:25