If you have created maps using Geoserver then you may aware
that those maps can be cached as image tiles using GeoWebCache. If you want to
get rid of another back-end server to render and serve your map, serving it as
map tiles might be a good idea. Open Layers ol.source.XYZ is the option provided for us to render a map
from cached image tiles. But with GeoWebCache caching mechanism there is a
little problem. XYZ source requires the tiles to be stored in a structure similar
to {z}/{x}/{y}.png where z is the zoom level and x,y is the coordinate of the
tile and GeoWebCache generated tiles are not in this format. OpenLayers gives us an option to provide a
url generation function as tileUrlFunction. I came up with functions below with the help of GeoWebCache.js
which is the OpenLayers 2 way of doing this.
var zeroPad = function(num, len, radix) { var str = num.toString(radix || 10); while (str.length < len) { str = "0" + str; } return str; };
var customUrlFunction = function(bounds) { var x = bounds[1]; var y = bounds[2]; var z = bounds[0]; var shift = z / 2 | 0; var half = Math.pow(2, shift + 1); var digits = 1; if (half > 10) { digits = ((Math.log(half) / Math.LN10).toFixed(14) | 0) + 1; } var halfX = x / half | 0; var halfY = y / half | 0; var path = [ gridsetName + "_" + zeroPad(z, 2), zeroPad(halfX, digits) + "_" + zeroPad(halfY, digits), zeroPad(x, 2 * digits) + "_" + zeroPad(y, 2 * digits) + "." + "png" ].join("/"); var base = url.replace(/\/$/, "") + "/"; return base + path; };
The gridsetName is the name of the GridSet which was used to cache the tiles in GeoServer, normally this is the projection, for example, 'EPSG:4327'. The url is the local folder where the tiles are located.
By default, openlayers start calculating the tile
coordinates starting from the bottom-left corner of the map. But Geoserver
cached tiles are named taking top-left corner as the origin. So to make it
right, when initializing the XYZ source, a tile grid must be provided with the
origin set to top left corner of the map.
var tileGrid = ol.tilegrid.createXYZ({ extent: mapExtent, tileSize: 256, origin: [mapExtent[0], mapExtent[1]] });
var tiled_layer = new ol.layer.Tile( { source: new ol.source.XYZ( { projection: projection, tileGrid: tileGrid, maxExtent: mapExtent, tileUrlFunction: customUrlFunction }) });
var url = “file/path/to/tiles/directory/”; var gridsetName= “name_of_the_Gridset”;
var projection = “projection_of_the_map”;
var mapExtent= [];
var zeroPad = function(num, len, radix) { var str = num.toString(radix || 10); while (str.length < len) { str = "0" + str; } return str; };
var customUrlFunction = function(bounds) { var x = bounds[1]; var y = bounds[2]; var z = bounds[0]; var shift = z / 2 | 0; var half = Math.pow(2, shift + 1); var digits = 1; if (half > 10) { digits = ((Math.log(half) / Math.LN10).toFixed(14) | 0) + 1; } var halfX = x / half | 0; var halfY = y / half | 0; var path = [ gridsetName + "_" + zeroPad(z, 2), zeroPad(halfX, digits) + "_" + zeroPad(halfY, digits), zeroPad(x, 2 * digits) + "_" + zeroPad(y, 2 * digits) + "." + "png" ].join("/"); var base = url.replace(/\/$/, "") + "/"; return base + path; };
var tileGrid = ol.tilegrid.createXYZ({ extent: mapExtent, maxZoom: 8, tileSize: 256, origin: [mapExtent[0], mapExtent[1]] });
var tiled_layer = new ol.layer.Tile( { source: new ol.source.XYZ( { projection: projection, tileGrid: tileGrid, maxExtent: mapExtent, tileSize: 256, tileUrlFunction: customUrlFunction }) });
var map = new ol.Map( { target: 'map', layers: [tiled_layer], view: new ol.View( { center: [(mapExtent[0]+mapExtent[2])/2, (mapExtent[1]+ mapExtent[3])/2], projection: projection }) });