Search code examples
openlayers-3

Is it possible to set different colors to each segment of a LineString without meeting a huge performance hit?


My openlayers 3 application draws several LineString features on the map (from a few dozen up to 2000-3000).

When setting different colors for each segment of the LineStrings, I meet a huge performance hit (starting from just a few LineStrings on the map). The zoom and pan become completely unresponsive making my aplication not usable in this form.

Since I don't want to set a new geometry for each segment (but only change its color), I imagine there must be a more performance effective way of achieving this ?

Here's my code :

var styleFunction = function(feature, resolution) {

    var i = 0, geometry = feature.getGeometry();

    geometry.forEachSegment(function (start, end) {

        color = colors[i];

        styles.push(new ol.style.Style({
            geometry: new ol.geom.LineString([start, end]),
            fill: new ol.style.Fill({
                color: color
            }),
            stroke: new ol.style.Stroke({
                color: color,
                width: 2
            })
        }));

        i++;
    });

    return styles;
}

var vectorLayer = new ol.layer.Vector({
    source: vectorSource,
    style: styleFunction
});

Solution

  • Since we could not solve the problem, even with tsauerwein's recommendations, this feature was put to the fridge for a while. Now we got back to it with fresh ideas and actually found a "solution".

    Something that I made not clear in the question is that segments of a LineString are colored according to a property of their starting point. Several consecutive segments may thus share the same color if the value of this property doesn't change between them.

    The idea is to avoid creating a new style for each and every segment but rather to create a new style only when necessary (when the color changes) :

    let i = 0,
        color = '#FE2EF7', //pink. should not be displayed
        previousColor = '#FE2EF7',
        lineString,
        lastCoordinate = geometry.getLastCoordinate();
    
    geometry.forEachSegment(((start, end) => {
    
            color = this.getColorFromProperty(LinePoints[i].myProperty);
    
            //First segment
            if (lineString == null) {
                lineString = new ol.geom.LineString([start, end]);
            } else {
    
                //Color changes: push the current segment and start a new one
                if (color !== previousColor) {
    
                    styles.push(new ol.style.Style({
                        geometry: lineString,
                        fill: new ol.style.Fill({
                            color: previousColor
                        }),
                        stroke: new ol.style.Stroke({
                            color: previousColor,
                            width: 2
                        })
                    }));
    
                    lineString = new ol.geom.LineString([start, end]);
    
                } else {
                    //Color is same: continue the current segment
                    lineString.appendCoordinate(end);
                }
    
                //Last segment
                if (end[0] === lastCoordinate[0] && end[1] === lastCoordinate[1]) {
                    styles.push(new ol.style.Style({
                        geometry: lineString,
                        fill: new ol.style.Fill({
                            color: color
                        }),
                        stroke: new ol.style.Stroke({
                            color: color,
                            width: 2
                        })
                    }));
                }
            }
    
            previousColor = color;
            i++;
        }