0

I'm using OpenLayers 7 to display a tile layer from a tile service. The service only has tiles up to a maximum zoom level. At higher zooms, I would like OL to fetch maximum zoom level tiles and display them upscaled. How do I do this?

Setting layer.setMaxZoom(SERVER_MAX_ZOOM) causes the layer to disappear completely beyond SERVER_MAX_ZOOM, so that's no good.

I've also tried a tile loader function that blocks requests for higher zoom levels. This causes OL to display upscaled tiles provided they'd already been loaded (due to useInterimTilesOnError), but it won't fetch new tiles of level SERVER_MAX_ZOOM after panning.

Demo: https://jsfiddle.net/jrwtc2df/4/

HTML:

<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v6.9.0/build/ol.js"></script>

<div id="map" style="position:absolute;top:0;left:0;height:100%;width:100%;"></div>

JS:

const osm = new ol.source.OSM();
const getTile = osm.getTileUrlFunction();
// Cause a load error above zoom level 8.
// This simulates a server which returns 404 above this level.
osm.setTileUrlFunction((coord) => coord[0] <= 8 ? getTile(coord) : 'http://localhost/');
const map = new ol.Map({
  target: 'map',
  layers: [
    new ol.layer.Tile({
      maxZoom: 10,
      source: osm,
    }),
  ],
  view: new ol.View({
    center: ol.proj.fromLonLat([0, 51.5]),
    zoom: 8,
    maxZoom: 10,
  }),
});

The demo starts at level 8. Zoom in to level 9 or 10 and you see upsampled imagery (good). But after panning away, OL only attempts to load level 9/10 tiles which are unavailable, and shows nothing (bad).

I can overcome this by also setting layer.setPreload(SERVER_MAX_ZOOM), but this fetches all zoom levels from 0 up to and including SERVER_MAX_ZOOM, which is quite wasteful.

I've thought of these other possible solutions:

  • A tile loader function that, when zoom > SERVER_MAX_ZOOM, loads the SERVER_MAX_ZOOM tile, renders the relevant part of the tile into a canvas and sets as the output tile's src. This seems wasteful of resources.
  • A tile loader function that, when zoom > SERVER_MAX_ZOOM, errors the request and tell the layer to add the correct SERVER_MAX_ZOOM tile to the tile queue, it should then be used as per setUseInterimTilesOnError(true). However I can't find a way to access the tile queue. I haven't implemented these yet, but might if there is no easier solution.
2
  • This is usually done by setting the maxZoom option on the source to SERVER_MAX_ZOOM
    – Mike
    Feb 22 at 10:23
  • As @Mike wrote in his comment, you have to set maxZoom on layer source, not on layer. In your sample code that would be const osm = new ol.source.OSM({maxZoom: 8});.
    – TomazicM
    Feb 22 at 15:31

1 Answer 1

0

The comment by @Mike is the answer - my mistake was confusing the maxZoom option of a tile SOURCE with the maxZoom option of a tile LAYER.

The LAYER's minZoom and maxZoom control the range of zoom levels over which the layer is displayed, as described in my question. The SOURCE's minZoom and maxZoom tell OpenLayers the range of zoom levels it can supply tiles at.

So the solution is to set the maxZoom option of the SOURCE to SERVER_MAX_ZOOM, and the maxZoom option of the LAYER to a higher value. Then when the displayed zoom level is higher than SERVER_MAX_ZOOM, OpenLayers will fetch tiles from the source at its maximum zoom level as required, and display them upscaled.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.