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
});
There are a few things that you can try to optimize:
Cache fill and stroke style
var fillStyles = colors.map(function(color, i) {
return new ol.style.Fill({
color: color
})
});
var strokeStyles = colors.map(function(color, i) {
return new ol.style.Stroke({
color: color,
width: 2
})
});
Cache the style for each feature
vectorSource.forEach(function(feature, i) {
var geometry = feature.getGeometry();
var styles = [];
var i = 0;
geometry.forEachSegment(function (start, end) {
styles.push(new ol.style.Style({
geometry: new ol.geom.LineString([start, end]),
fill: fillStyles[i],
stroke: strokeStyles[i]
}));
i++;
});
feature.setStyle(styles);
});
Disable that the rendering is updated during animations and interactions
var vectorLayer = new ol.layer.Vector({
source: vectorSource,
updateWhileAnimating: false,
updateWhileInteracting: false
});
See ol.layer.Vector.
If all this doesn't help, you might also want to take a look at ol.source.ImageVector(example).
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++;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With