1

Apologies in advance, this is my first StackOverflow question.

I need to use an OpenLayers layer extent to place a boundary on a region of the map in order to prevent an XYZSource's url from trying to grab tiles that don't exist (resulting in 404 error messages).

I found this example which was helpful: How can you set the extent of a XYZ source using OpenLayers 6?

Here are the problems I ran into below:

Using an extent on an XYZSource directly

If I use an extent on the XYZSource, the extent expands and contracts at different zoom levels and never accurately shows the bounding box I expect.

Here is how it looks at 2 different zoom levels:

close up zoom no zoom

The good news is is that I can pan my map infinitely in either direction and the extent will always be displayed regardless of how many revolutions the map has moved.

Using an extent on the TileLayer itself

If I put the extent on the TileLayer instead, the extent stays the correct size regardless of zoom level, but when I pan in either direction beyond 1 revolution, the extent disappears. Here is how the bounding box should look:

constant size

Goal

My goal is to have the extent maintain a constant size and also always be displayed regardless of how many revolutions the map is panned in either direction.

Any help or suggestions would be greatly appreciated!

Code

  ngOnInit(): void {
    const token = 'sWmX5SwjXmDHtQNDFmI7CyUgBqUvRzxpT6CM5sSbBLqxd3bpJxNNAZ2O4Rivf1Eo';
    const urlDark = 'https://tile.jawg.io/jawg-dark/{z}/{x}/{y}.png?access-token=' + token;
    const urlStreets = 'https://tile.jawg.io/jawg-streets/{z}/{x}/{y}.png?access-token=' + token;

    // http://bboxfinder.com/#8.035094,68.964958,32.415038,89.179802
    const indiaExtent = [7677144.0284, 897408.9306, 9927450.1411, 3817914.9073];

    const defaultTileGrid = createXYZ({ extent: getProjection('EPSG:3857')?.getExtent() });
    const res = defaultTileGrid.getResolutions();
    const org = defaultTileGrid.getOrigin(16);

    this.map = new Map({
      view: new View({
        center: fromLonLat([78.781414, 22.164514]),
        zoom: 4,
      }),
      layers: [],
      target: 'ol-map',
    });

    var baseLayer = new TileLayer({
      source: new XYZSource({
        url: urlDark,
      })
    });

    var layerA = new TileLayer({
      source: new XYZSource({
        url: urlStreets,
        tileGrid: new TileGrid({
          origin: org,
          resolutions: res,
          extent: indiaExtent
        })
      })
    });

    var layerB = new TileLayer({
      extent: indiaExtent,
      source: new XYZSource({
        url: urlStreets,
      })
    });
  
    this.map.addLayer(baseLayer);
    this.map.addLayer(layerA);
    //this.map.addLayer(layerB);
  }
}

Stackblitz Link https://stackblitz.com/edit/angular-ivy-xv3xhn

jeffdbx
  • 11
  • 2
  • Layer extent corresponds to an extent in the view so it does not wrap. Source extent is the same as tile grid extent - any tile which is partially in the extent will be rendered. A different approach which should work would be to the layer as in https://openlayers.org/en/latest/examples/layer-clipping-vector.html, but move the clipping polygon according to the world in view (and include adjacent worlds) to handle wrapping https://codesandbox.io/s/layer-clipping-vector-forked-j2sw6x?file=/main.js – Mike Jul 20 '23 at 10:07
  • Awseome, thanks Mike! I will play with this and see if I can get it working on my end. Side question: (probably dumb question) Do you know why the Source extent does not maintain a constant size (around India) when I zoom in and out? It seems so close to what I need out of the box, but I just haven't figured out why its size doesn't remain constant. Thanks again for your time! – jeffdbx Jul 20 '23 at 12:14
  • Source extent is the same as tilegrid extent, it prevents tiles being loaded if they are completely outside the extent, but not if they overlap the edge of the extent. – Mike Jul 20 '23 at 12:19
  • Ahh got it. You said that in your first comment, but it didn't register in my smooth brain. Thank you sir! – jeffdbx Jul 20 '23 at 12:23
  • @Mike Your answers really helped me out and it turns out that your answer linked in my original post is working well for me after all. If you add your first comment above as an answer here, I will set it as the chosen answer. Thanks again! – jeffdbx Jul 25 '23 at 19:24

0 Answers0