diff --git a/examples/tiles/main.js b/examples/tiles/main.js index 6d93191b29..a1ab64e4bc 100644 --- a/examples/tiles/main.js +++ b/examples/tiles/main.js @@ -1,3 +1,4 @@ +/* globals $, geo */ // This example should be tried with different query strings. /* Many parameters can be adjusted via url query parameters: @@ -27,8 +28,8 @@ * maxBoundsTop: maximum bounds top value. * opacity: a css opacity value (typically a float from 0 to 1). * projection: 'parallel' or 'projection' for the camera projection. - * renderer: 'vgl' (default), 'canvas', 'd3', 'null', or 'html'. This picks the - * renderer for map tiles. null or html uses the html renderer. + * renderer: 'vgl' (default), 'canvas', 'd3', 'null', or 'html'. This picks + * the renderer for map tiles. null or html uses the html renderer. * round: 'round' (default), 'floor', 'ceil'. * subdomains: a comma-separated string of subdomains to use in the {s} part * of the url parameter. If there are no commas in the string, each letter @@ -159,6 +160,13 @@ $(function () { }; layerParams.attribution = ''; layerParams.tileRounding = Math.ceil; + layerParams.tilesAtZoom = function (level) { + var scale = Math.pow(2, layerParams.maxLevel - level); + return { + x: Math.ceil(w / (layerParams.tileWidth || 256) / scale), + y: Math.ceil(h / (layerParams.tileHeight || 256) / scale) + }; + }; } // Parse additional query options if (query.x !== undefined) { diff --git a/src/tileLayer.js b/src/tileLayer.js index bebfb8ea0c..f46dc0e250 100644 --- a/src/tileLayer.js +++ b/src/tileLayer.js @@ -81,6 +81,9 @@ module.exports = (function () { * The tile width as displayed without overlap * @param {number} [options.tileHeight=256] * The tile height as displayed without overlap + * @param {function} [options.tilesAtZoom=null] + * A function that is given a zoom level and returns {x: (num), y: (num)} + * with the number of tiles at that zoom level. * @param {number} [options.cacheSize=400] The maximum number of tiles to * cache. The default is 200 if keepLower is false. * @param {bool} [options.keepLower=true] @@ -230,6 +233,9 @@ module.exports = (function () { * @returns {{x: nx, y: ny}} The number of tiles in each axis */ this.tilesAtZoom = function (level) { + if (this._options.tilesAtZoom) { + return this._options.tilesAtZoom.call(this, level); + } var s = Math.pow(2, level); return {x: s, y: s}; }; diff --git a/tests/cases/tileLayer.js b/tests/cases/tileLayer.js index 86ba852ebe..542a1405b2 100644 --- a/tests/cases/tileLayer.js +++ b/tests/cases/tileLayer.js @@ -347,7 +347,11 @@ describe('geo.tileLayer', function () { tileRounding: function () {}, attribution: 'My awesome layer', tileOffset: function () {}, - topDown: true + topDown: true, + tilesAtZoom: function (level) { + var s = Math.pow(2, level); + return {x: s, y: Math.ceil(s * 3 / 4)}; + } }; opts.originalUrl = opts.url; it('Check tileLayer options', function () { @@ -401,6 +405,15 @@ describe('geo.tileLayer', function () { l.subdomains(['ab', 'c']); expect(l.subdomains()).toEqual(['ab', 'c']); }); + it('tilesAtZoom', function () { + var m = map(), l; + opts.map = m; + l = geo.tileLayer(opts); + expect(l.tilesAtZoom(0)).toEqual({x: 1, y: 1}); + expect(l.tilesAtZoom(1)).toEqual({x: 2, y: 2}); + expect(l.tilesAtZoom(2)).toEqual({x: 4, y: 3}); + expect(l.tilesAtZoom(3)).toEqual({x: 8, y: 6}); + }); }); describe('Public utility methods', function () { describe('isValid', function () {