diff --git a/changelog/upgrade-notes.md b/changelog/upgrade-notes.md index 5ad22c71b8..088f396158 100644 --- a/changelog/upgrade-notes.md +++ b/changelog/upgrade-notes.md @@ -2,6 +2,15 @@ ### Next release +#### Simpler `ol.source.Zoomify` `url` configuration + +Instead specifying a base url, the `url` for the `ol.source.Zoomify` source can now be a template. The `{TileGroup}`, `{x}`, `{y}`, `{z}` and placeholders must be included in the `url` in this case. the `url` can now also include subdomain placeholders: +```js +new ol.source.Zoomify({ + url: 'https://{a-f}.example.com/cgi-bin/iipsrv.fcgi?zoomify=/a/b/{TileGroup}/{z}-{x}-{y}.jpg' +}); +``` + #### Removal of deprecated methods The deprecated `ol.animation` functions and `map.beforeRender()` method have been removed. Use `view.animate()` instead. diff --git a/externs/olx.js b/externs/olx.js index 1a389cbb5b..7887eecd55 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -6759,7 +6759,13 @@ olx.source.ZoomifyOptions.prototype.reprojectionErrorThreshold; /** - * Prefix of URL template. + * URL template or base URL of the Zoomify service. A base URL is the fixed part + * of the URL, excluding the tile group, z, x, and y folder structure, e.g. + * `http://my.zoomify.info/IMAGE.TIF/`. A URL template must include + * `{TileGroup}`, `{x}`, `{y}`, and `{z}` placeholders, e.g. + * `http://my.zoomify.info/IMAGE.TIF/{TileGroup}/{z}-{x}-{y}.jpg`. + * A `{?-?}` template pattern, for example `subdomain{a-f}.domain.com`, may be + * used instead of defining each one separately in the `urls` option. * @type {!string} * @api */ diff --git a/src/ol/source/zoomify.js b/src/ol/source/zoomify.js index af575569d5..adfe25be8b 100644 --- a/src/ol/source/zoomify.js +++ b/src/ol/source/zoomify.js @@ -3,6 +3,7 @@ goog.provide('ol.source.Zoomify'); goog.require('ol'); goog.require('ol.ImageTile'); goog.require('ol.TileState'); +goog.require('ol.TileUrlFunction'); goog.require('ol.asserts'); goog.require('ol.dom'); goog.require('ol.extent'); @@ -83,31 +84,51 @@ ol.source.Zoomify = function(opt_options) { }); var url = options.url; + if (url && url.indexOf('{TileGroup}') == -1) { + url += '{TileGroup}/{z}-{x}-{y}.jpg'; + } + var urls = ol.TileUrlFunction.expandUrl(url); /** - * @this {ol.source.TileImage} - * @param {ol.TileCoord} tileCoord Tile Coordinate. - * @param {number} pixelRatio Pixel ratio. - * @param {ol.proj.Projection} projection Projection. - * @return {string|undefined} Tile URL. + * @param {string} template Template. + * @return {ol.TileUrlFunctionType} Tile URL function. */ - function tileUrlFunction(tileCoord, pixelRatio, projection) { - if (!tileCoord) { - return undefined; - } else { - var tileCoordZ = tileCoord[0]; - var tileCoordX = tileCoord[1]; - var tileCoordY = -tileCoord[2] - 1; - var tileIndex = - tileCoordX + - tileCoordY * tierSizeInTiles[tileCoordZ][0] + - tileCountUpToTier[tileCoordZ]; - var tileGroup = (tileIndex / ol.DEFAULT_TILE_SIZE) | 0; - return url + 'TileGroup' + tileGroup + '/' + - tileCoordZ + '-' + tileCoordX + '-' + tileCoordY + '.jpg'; - } + function createFromTemplate(template) { + + return ( + /** + * @param {ol.TileCoord} tileCoord Tile Coordinate. + * @param {number} pixelRatio Pixel ratio. + * @param {ol.proj.Projection} projection Projection. + * @return {string|undefined} Tile URL. + */ + function(tileCoord, pixelRatio, projection) { + if (!tileCoord) { + return undefined; + } else { + var tileCoordZ = tileCoord[0]; + var tileCoordX = tileCoord[1]; + var tileCoordY = -tileCoord[2] - 1; + var tileIndex = + tileCoordX + + tileCoordY * tierSizeInTiles[tileCoordZ][0] + + tileCountUpToTier[tileCoordZ]; + var tileGroup = (tileIndex / ol.DEFAULT_TILE_SIZE) | 0; + var localContext = { + 'z': tileCoordZ, + 'x': tileCoordX, + 'y': tileCoordY, + 'TileGroup': 'TileGroup' + tileGroup + }; + return template.replace(/\{(\w+?)\}/g, function(m, p) { + return localContext[p]; + }); + } + }); } + var tileUrlFunction = ol.TileUrlFunction.createFromTileUrlFunctions(urls.map(createFromTemplate)); + ol.source.TileImage.call(this, { attributions: options.attributions, cacheSize: options.cacheSize, diff --git a/test/spec/ol/source/zoomify.test.js b/test/spec/ol/source/zoomify.test.js index 9bd4ae9597..ea5e513e8e 100644 --- a/test/spec/ol/source/zoomify.test.js +++ b/test/spec/ol/source/zoomify.test.js @@ -11,7 +11,7 @@ describe('ol.source.Zoomify', function() { var w = 1024; var h = 512; var size = [w, h]; - var url = 'zoomify-url/'; + var url = 'zoomify-url/{TileGroup}/{z}-{x}-{y}.jpg'; var proj = new ol.proj.Projection({ code: 'ZOOMIFY', units: 'pixels', @@ -167,7 +167,7 @@ describe('ol.source.Zoomify', function() { describe('generated tileUrlFunction', function() { - it('creates an expected tileUrlFunction', function() { + it('creates an expected tileUrlFunction with template', function() { var source = getZoomifySource(); var tileUrlFunction = source.getTileUrlFunction(); // zoomlevel 0 @@ -179,6 +179,20 @@ describe('ol.source.Zoomify', function() { expect(tileUrlFunction([1, 1, -2])).to.eql('zoomify-url/TileGroup0/1-1-1.jpg'); }); + it('creates an expected tileUrlFunction without template', function() { + var source = new ol.source.Zoomify({ + url: 'zoomify-url/', + size: size + }); + var tileUrlFunction = source.getTileUrlFunction(); + // zoomlevel 0 + expect(tileUrlFunction([0, 0, -1])).to.eql('zoomify-url/TileGroup0/0-0-0.jpg'); + // zoomlevel 1 + expect(tileUrlFunction([1, 0, -1])).to.eql('zoomify-url/TileGroup0/1-0-0.jpg'); + expect(tileUrlFunction([1, 1, -1])).to.eql('zoomify-url/TileGroup0/1-1-0.jpg'); + expect(tileUrlFunction([1, 0, -2])).to.eql('zoomify-url/TileGroup0/1-0-1.jpg'); + expect(tileUrlFunction([1, 1, -2])).to.eql('zoomify-url/TileGroup0/1-1-1.jpg'); + }); it('returns undefined if no tileCoord passed', function() { var source = getZoomifySource(); var tileUrlFunction = source.getTileUrlFunction();