OpenLayers v6.3.1: Loop on using postrender event

Viewed 79

I want to show a map with features similar to a printed map. So I want to show a lat/lon grid. In the active viewport I want to show about 4 lines in each direction, so an a small zoom I maybe show 0°, 10°, 20°, 30°, on a large zoom 30°15'2", 30°15'3", 30°15'4", 30°15'5". A simple solution would be to define all this grid lines as vectors, and define that minutes and seconds are only shown above a certain zoom level. The disadvantage of this approach is that I have to define 360x60x60 meridian vectors, but only 4 are really used. Instead, I only define the lines needed, plus some extra ones outside the map. So I can move and resize the map, and, if needed, new lines are calculated on the fly.

These lines are only shown on the map. But I want to elongate them, so they are also shown and labeled on the border of the map. I do this by placing a svg layer under the map. I know the pixel coordinates of my grid, so I can draw the extentions on my svg layer. This works fine, until I move or zoom the map. Now the map grid does not fit to the border grid, which has to be recalculated.

Because I want to show smooth movements not only in the map, but also in the border, I recalculate on postrender (which occurs about 20 to 60 times when I move the map). The result looks nice and smooth.

The problem is: I draw the grid lines in a postrender triggerd function. The drawing of the lines is considered as new rendering, so postrender is triggered again, which causes a unwanted loop. Is there a possibility to stop the loop?

You can look at an example at Map grid example Just switch on a grid (Greenwich or Ferro), and look at the postrendercount in the left bottom corner.

The main code I used is

var vectorSource = new ol.source.Vector();
var vectorLineLayer = new ol.layer.Vector({
source: vectorSource
});
var map = new ol.Map({
target: 'map',
layers: [
    new ol.layer.Tile({
        source: new ol.source.OSM()     }), 
  vectorLineLayer   ],
view: new ol.View({
    center: ol.proj.fromLonLat([14.125, 47.594]),
    zoom: 6 })    });

map.on('postrender', function () {
   debWriteln([['postrendercount',postrendercount++]]);
   drawcoordinates();});
function drawcoordinates() {
...
vectorSource.clear();
...
var featureLine = new ol.Feature({
            geometry: new ol.geom.LineString(points)                });
...
vectorSource.addFeature(featureLine);}
1 Answers

If nothing has changed you do not need to repeat the action. The simplest thing to check would be the extent which was rendered

var renderExtent;

map.on('postrender', function (event) {
  if (event.frameState.extent.toString() === renderExtent) {
    return;
  }
  renderExtent = event.frameState.extent.toString();


}); 
Related