Configuring ZoomLevels in OpenLayers

The OpenLayers Map is designed to display each of its layers at different levels of Scale or Resolution.

The map object refers to these levels as ZoomLevels, and allows each layer to define its own ZoomLevels as it sees fit.

To configure the ZoomLevels of any OpenLayers Layer, the user sets various properties in the options array on initialization.

Normal Layers

For normal layers which are based off of OpenLayers.Layer and are able to display at any resolution, there exist a multitude of different ways to configure the ZoomLevels and their respective scales and resolutions.

Resolutions Array: To translate ZoomLevels into Resolution, a resolutions array is populated, which is a list of the different supported resolutions for the layer. The ZoomLevel then is just an index into this resolutions array. A resolution array starts a 0 and goes until numZoomLevels-1.

Example:

If the layer's resolution is [a,b,c], then ZoomLevel 0 is a, ZoomLevel 1 is b, and so on.

Ways to Configure the Resolutions Array

Available Options:

  • scales - Array -- list of preset scale values
  • resolutions - Array -- list of preset resolution values
  • minScale - float -- the minimum scale value at which the layer should display
  • maxScale - float -- the maximum scale value at which the layer should display
  • maxResolution - float -- the maximum resolution value at which the layer should display
  • minResolution - float -- the minimum resolution value at which the layer should display
  • minExtent - OpenLayers.Bounds -- The minimum viewable extent for the layer.
  • maxExtent - OpenLayers.Bounds -- The maximum viewable extent for the layer.
  • numZoomLevels - int -- Total number of zoom levels
  • units - String - The units in which to display the layer. This affects the Scale-Resolution calculation.

Example Declarations:

    var options = { scales: [50000000, 30000000, 10000000, 5000000],
                    resolutions: [1.40625,0.703125,0.3515625,0.17578125,0.087890625,0.0439453125],
                    minScale: 50000000,
                    maxResolution: "auto",
                    maxExtent: new OpenLayers.Bounds(-180, -90, 180, 90),
                    maxResolution: 0.17578125,
                    maxScale: 10000000,
                    minResolution: "auto",
                    minExtent: new OpenLayers.Bounds(-1, -1, 1, 1),
                    minResolution: 0.0439453125,
                    numZoomLevels: 5,
                    units: "degrees"
                  };
    map = new OpenLayers.Map( $('map') , options);

Obviously all of the configuration options listed above can not be set at once. Since they can be conflicting, they have been prioritized, as follows:

  • Preset zoom levels - ZoomLevels are determined by pre-set arrays of scale or resolution
    • scales - The 'resolutions' array is filled with these scales, each directly converted to resolution.
    • resolutions - The 'resolutions' array is taken directly from the options.

Examples:

    var options = { scales: [50000000, 30000000, 10000000, 5000000] };
    map = new OpenLayers.Map( $('map') , options);
    var options = { resolutions: [1.40625,0.703125,0.3515625,0.17578125,0.087890625,0.0439453125] };
    map = new OpenLayers.Map( $('map') , options);
  • maxResolution and numZoomLevels - ZoomLevels are determined based on a maximum resolution and the number of desired ZoomLevels
    • Determining maxResolution
      • minScale - Resolution value is translated from scale using units
      • maxExtent AND maxResolution == "auto" - Resolution is calculated based on map's div size and the maxExtent property. If maxExtent is not specified, a default value is inherited from the map.
      • maxResolution - Resolution value is taken directly from the value specified in the layer options. If no value specified, the default is taken from the map.
    • Determining numZoomLevels
      • Calculated based on ratio of maxResolution to minResolution
        • Determining minResolution
          • maxScale - Resolution value is translated from scale using units
          • minExtent AND minResolution == "auto" - Resolution is calculated based on map's div size and the minExtent property. minExtent must be specified, as a default value is NOT inherited from the map.
          • minResolution - Resolution value is taken directly from the value specified in the layer options. If no value specified, minResolutions remains null, and numZoomLevels is taken directly (below)
      • numZoomLevels - numZoomLevels value is taken directly from the value specified in the layer options. If no value is specified, the default is taken from the map.

Examples:

maxResolutionConverted from minScale using specified units
numZoomLevelsDefault from map
    var options = { minScale: 50000000,
                    units: "degrees"
                  };
    map = new OpenLayers.Map( $('map') , options);


maxResolutionCalculated based on div size and default maxExtent from map
numZoomLevelsCalculated using ratio of maxResolution/minResolution
    var options = { maxResolution: "auto",
                    maxExtent: new OpenLayers.Bounds(-180, -90, 180, 90),
                    minResolution: 0.0439453125
                  };
    map = new OpenLayers.Map( $('map') , options);


maxResolutionSpecified
numZoomLevelsSpecified
    var options = { maxResolution: 0.17578125,
                    numZoomLevels: 15
                  };
            map = new OpenLayers.Map( $('map') , options);


maxResolutionDefault from map
numZoomLevelsConverted maxScale (using default units from map) to minResolution, then uses ratio of maxResolution/minResolution to calculate numZoomLevels
    var options = { maxScale: 10000000 };
    map = new OpenLayers.Map( $('map') , options);


maxResolutionSpecified
numZoomLevelsCalculated minResolution based on div size and default minExtent from map, then uses ratio of maxResolution/minResolution to calculate numZoomLevels
    var options = { maxResolution: 0.17578125,
                    minResolution: "auto",
                    minExtent: new OpenLayers.Bounds(-1, -1, 1, 1),
                  };
    map = new OpenLayers.Map( $('map') , options);

3rd Party Layers

Most 3rd party layers like GMaps or VirtualEarth already have their ZoomLevels-to-Resolutions list pre-set, so the only way the user can limit which zoom levels are supported by the layer is by setting the 'minZoomLevel', 'maxZoomLevel', and 'numZoomLevels' properties on the layer.

Available options:

  • minZoomLevel
  • maxZoomLevel
  • numZoomLevels

The minZoomLevel property tells OpenLayers what the user wishes to be the first (furtherst zoomed out) zoom level displayed by the layer. This property is always taken into account as-is. If 'minZoomLevel' is not set, or if it is set below the 'MIN_ZOOM_LEVEL' minimum threshold, the layer's 'minZoomLevel' property is simply set to 'MIN_ZOOM_LEVEL' (See below for an explanation/warning regarding this constant).

Now for 'maxZoomLevel' and 'numZoomLevels'. As with the other layers, we need rules of precedence to determine exactly how these values are interepreted in order to calculate the final resolutions array. We will be reading the above properties from the layer first, and later -- if they are not specified on the layer -- from the map. They will help us to determine how many entries from the resolutions array to expose.

The precedence rules are then as following:

  1. numZoomLevels set on layer
  2. maxZoomLevel set on layer
  3. numZoomLevels set on map
  4. maxZoomLevel set on map*
  5. none of the above*

For cases 1 & 3, the final 'numZoomLevels' for the layer is simply the 'numZoomLevels' value itself as specified.

For cases 2 & 4, the final 'numZoomLevels' for the layer is the 'maxZoomLevel' minus the 'minZoomLevel' (plus one).

In all four of the above cases, if the final 'numZoomLevels' ends up surpassing the specified 'MAX_ZOOM_LEVEL' constant as set on the layer, we clip it such that it remains within the bounds. (Again, see below for an explanation/warning regarding this constant).

In case 5, where neither 'numZoomLevels' nor 'maxZoomLevel' is specified on either the layer or the map, then we calculate the layer's 'numZoomLevels' based on the maximum possible, as determined by the layer's constants.

*Note that options (4) and (5) are only possible if the user explicitly sets the 'numZoomLevels' property on the map to null, since it is set by default to 16.

...If all this doesn't make much sense, the general idea of things is that specifying 'numZoomLevels' takes precedence over a specified 'maxZoomLevel', and either of those options specified on the layer itself takes precedence over their counterparts specified on the map.

Examples:

            map = new OpenLayers.Map( $('map') );

            var layer  = new OpenLayers.Layer.Google( "Google",
             { minZoomLevel: 3, maxZoomLevel: 8 });

            // layer.numZoomLevels == 6
            map = new OpenLayers.Map( $('map') );

            var layer = new OpenLayers.Layer.VirtualEarth( "VE",
             { minZoomLevel: 3, numZoomLevels: 6 });

            // layer.numZoomLevels == 6
            map = new OpenLayers.Map( $('map') );

            var layer = new OpenLayers.Layer.VirtualEarth( "VE",
             { minZoomLevel: 3, numZoomLevels: 10, maxZoomLevel: "Peter Pan" });

            // layer.numZoomLevels == 10
            // 'numZoomLevels' takes precedence over 'maxZoomLevel' (which is completely ignored)
            map = new OpenLayers.Map( $('map') );

            var layer = new OpenLayers.Layer.Yahoo( "Yahoo",
             { numZoomLevels: 7 });

            //layer.numZoomLevels == 7
            map = new OpenLayers.Map( $('map') );

            var layer = new OpenLayers.Layer.Google( "Yahoo",
             { minZoomLevel: 2 });

            //layer.numZoomLevels == 16 (value taken from map's default)
            map = new OpenLayers.Map( $('map') );

            var layer = new OpenLayers.Layer.Yahoo( "Yahoo",
             { minZoomLevel: 10 });

            //layer.numZoomLevels == 6
            // Default 'numZoomLevels' of 16 taken from map, but Yahoo layer's MAX_ZOOM_LEVEL is 15, and 15 - 10 + 1 = 6. We can't show 16 zoom levels starting from level 10, so we will show 6.
            map = new OpenLayers.Map( $('map') );
            map.numZoomLevels = null; //explicit nullification

            var layer = new OpenLayers.Layer.Yahoo( "Yahoo",
             { minZoomLevel: 3 });

            //layer.numZoomLevels == 13
            // No 'maxZoomLeves' or 'numZoomLevels' defined on map or layer, so since Yahoo layer's MAX_ZOOM_LEVEL is 15: 15 - 3 + 1 = 13. 

TMS Layers

Setting the resolutions array in the traditional manner does not work with TMS layers by design. Instead of removing values from the resolutions array to restrict zoom levels (for unrendered TMS layers or other reasons), include both a serverResolutions array and a resolutions array. The serverResolutions array should include all resolutions available (whether rendered or not) on the server, while the resolutions array should have all resolutions that are presented to the user - therefore the resolutions array should be a subset of serverResolutions. For instance,

resolutions: [0.17578125, 0.087890625, 0.0439453125],
serverResolutions: [0.703125, 0.3515625, 0.17578125, 0.087890625, 0.0439453125],

Note: Some users may have noticed the existence of 'MIN_ZOOM_LEVELS' and 'MAX_ZOOM_LEVELS' properties as defined on the 3rd party layers. These are constant values and should not be modified. They are set by the creators of the 3rd party layers to specify to the FixedZoomLevels class the specifics of setting up their resolutions arrays. I repeat: these should *not* be modified by users: use instead the three options as explained above ('minZoomLevel', 'maxZoomLevel', and 'numZoomLevels')