Search code examples
javascriptopenlayers

Memory issue when trying to use minZoom on XYZ source


I'm trying to set a minimum zoom at which to show an XYZ source in my map in OpenLayers, but whenever I set it, the whole map has a memory issue and crashes. maxZoom works just fine.

I was originally using OpenLayers in React, but after running into this issue, I stripped it down as much as possible to see if I could fix it (I couldn't). Here's my code now:

import 'ol/ol.css';
import {Map, View} from 'ol';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
import XYZ from 'ol/source/XYZ.js';

const map = new Map({
  target: 'map',
  layers: [
    new TileLayer({
      source: new OSM()
    }),
    new TileLayer({
      source: new XYZ({
        url: 'http://myserver.com/tiles/{z}/{x}/{y}/',
        minZoom: 14,
        maxZoom: 19
      })
    })
  ],
  view: new View({
    center: [0, 0],
    zoom: 3
  })
});

What I'm intending to happen is to have the map load at zoom level 3, then when you zoom to level 14 the myserver.com tiles start showing. With the code as above, the page just loads and loads until Chrome says "Paused before potential out-of-memory crash" (basically the same for Firefox). If I take out this line:

minZoom: 14,

it loads fine. I've tried setting the minZoom to different values with no luck.


Solution

  • The maxResolution will be the resolution of the tiles at zoom level 14. It's exclusive so increase it slightly to include level 14, then the layer will only visible at level 14 and more

    import 'ol/ol.css';
    import {Map, View} from 'ol';
    import TileLayer from 'ol/layer/Tile';
    import OSM from 'ol/source/OSM';
    import XYZ from 'ol/source/XYZ.js';
    import {createXYZ} from 'ol/tilegrid';
    
    const map = new Map({
      target: 'map',
      layers: [
        new TileLayer({
          source: new OSM()
        }),
        new TileLayer({
          source: new XYZ({
            url: 'http://myserver.com/tiles/{z}/{x}/{y}/',
            maxZoom: 19
          }),
          maxResolution: createXYZ().getResolution(14) * 1.01
        })
      ],
      view: new View({
        center: [0, 0],
        zoom: 3
      })
    });
    

    If you want the layer to remain visible but show no addition detail after zoom 19 maxZoom: 19 is sufficient. If don't want it to be visible set minResolution: createXYZ().getResolution(19) on the layer (minResolution is inclusive).