From 08abab9d926f2d2018f82f0115ca35056cb3d8bc Mon Sep 17 00:00:00 2001 From: David Manthey Date: Thu, 25 May 2017 12:30:06 -0400 Subject: [PATCH] Several minor improvements. - When calling a tile url function, use the layer as the context. This would allow, for instance, two layers in different projections to use the same function which could then use this.gcsTileBounds() to determine the extent of the tile correctly for the layer. - Allow getting and setting the animation queue. This allows, for instance, linking two map's animation queues after they have been created. - Allow getting and setting the autoResize flag. --- examples/wms/main.js | 2 +- src/d3/d3Renderer.js | 6 +-- src/map.js | 82 +++++++++++++++++++++++++++++++++++----- src/osmLayer.js | 5 ++- src/registry.js | 1 + src/tileLayer.js | 5 ++- tests/cases/map.js | 26 +++++++++++++ tests/cases/osmLayer.js | 15 +++++++- tests/cases/tileLayer.js | 8 +++- 9 files changed, 129 insertions(+), 21 deletions(-) diff --git a/examples/wms/main.js b/examples/wms/main.js index 4119d48eee..0372796c90 100644 --- a/examples/wms/main.js +++ b/examples/wms/main.js @@ -17,7 +17,7 @@ $(function () { wms.url( function (x, y, zoom) { // Compute the bounding box - var bb = wms.gcsTileBounds({x: x, y: y, level: zoom}, projection); + var bb = this.gcsTileBounds({x: x, y: y, level: zoom}, projection); var bbox_mercator = bb.left + ',' + bb.bottom + ',' + bb.right + ',' + bb.top; // Set the WMS server parameters diff --git a/src/d3/d3Renderer.js b/src/d3/d3Renderer.js index d02cd4d8ef..3dcd9ed326 100644 --- a/src/d3/d3Renderer.js +++ b/src/d3/d3Renderer.js @@ -189,9 +189,9 @@ var d3Renderer = function (arg) { } m_diagonal = Math.pow(width * width + height * height, 0.5); m_corners = { - upperLeft: map.displayToGcs({'x': 0, 'y': 0}, null), - lowerRight: map.displayToGcs({'x': width, 'y': height}, null), - center: map.displayToGcs({'x': width / 2, 'y': height / 2}, null) + upperLeft: map.displayToGcs({x: 0, y: 0}, null), + lowerRight: map.displayToGcs({x: width, y: height}, null), + center: map.displayToGcs({x: width / 2, y: height / 2}, null) }; } diff --git a/src/map.js b/src/map.js index 59c7debdb6..45dba89d6f 100644 --- a/src/map.js +++ b/src/map.js @@ -123,6 +123,7 @@ var map = function (arg) { m_clampBoundsY, m_clampZoom, m_animationQueue = arg.animationQueue || [], + m_autoResize = arg.autoResize === undefined ? true : arg.autoResize, m_origin; /* Compute the maximum bounds on our map projection. By default, x ranges @@ -147,11 +148,12 @@ var map = function (arg) { m_maxBounds.right - m_maxBounds.left) / 256); m_camera.viewport = { - width: m_width, height: m_height, - left: m_node.offset().left, top: m_node.offset().top + width: m_width, + height: m_height, + left: m_node.offset().left, + top: m_node.offset().top }; arg.center = util.normalizeCoordinates(arg.center); - arg.autoResize = arg.autoResize === undefined ? true : arg.autoResize; m_clampBoundsX = arg.clampBoundsX === undefined ? false : arg.clampBoundsX; m_clampBoundsY = arg.clampBoundsY === undefined ? true : arg.clampBoundsY; m_clampZoom = arg.clampZoom === undefined ? true : arg.clampZoom; @@ -180,6 +182,62 @@ var map = function (arg) { return Math.pow(2, -zoom) * m_unitsPerPixel; }; + //////////////////////////////////////////////////////////////////////////// + /** + * Get/set the animation queue. Two maps can share a single animation queue + * to ensure synchronized animations. When setting, the animation queue will + * merge values from the existing queue into the new queue. + * + * @param {array} [queue] The animation queue to use. + * @returns {array|this} The current animation queue or the current map. + */ + //////////////////////////////////////////////////////////////////////////// + this.animationQueue = function (queue) { + if (queue === undefined) { + return m_animationQueue; + } + if (queue !== m_animationQueue) { + if (m_animationQueue.length) { + /* If the specified queue already has data in, don't copy the 0th + * element of the existing queue, since the 0th element is always the + * actual requestAnimationFrame reference. In this case, cancel the + * existing requestAnimationFrame. By using a property of window, + * tests can override this if needed. */ + if (queue.length && queue[0] !== m_animationQueue[0]) { + window['cancelAnimationFrame'](m_animationQueue[0]); + } + for (var i = queue.length ? 1 : 0; i < m_animationQueue.length; i += 1) { + queue.push(m_animationQueue[i]); + } + } + m_animationQueue = queue; + } + return this; + }; + + //////////////////////////////////////////////////////////////////////////// + /** + * Get/set the autoResize flag. + * + * @param {boolean} [autoResize] Truthy to automaticaly resize the map when + * the size of the browser window changes. + * @returns {boolean|this} The current state of autoResize or the current map. + */ + //////////////////////////////////////////////////////////////////////////// + this.autoResize = function (autoResize) { + if (autoResize === undefined) { + return m_autoResize; + } + if (autoResize !== m_autoResize) { + $(window).off('resize', resizeSelf); + m_autoResize = autoResize; + if (m_autoResize) { + $(window).on('resize', resizeSelf); + } + } + return this; + }; + //////////////////////////////////////////////////////////////////////////// /** * Get/set the `clampBoundsX` setting. If changed, adjust the bounds of the @@ -653,8 +711,10 @@ var map = function (arg) { m_this.zoom(newZoom); } m_this.camera().viewport = { - width: m_width, height: m_height, - left: m_node.offset().left, top: m_node.offset().top + width: m_width, + height: m_height, + left: m_node.offset().left, + top: m_node.offset().top }; m_this.center(oldCenter); @@ -1053,7 +1113,7 @@ var map = function (arg) { * * @param {array} p0 An array of numbers to interpolate from. * @param {array} p1 An array of numbers to interpolate to. - * @return {function} A function that, given `t`, returns an array of + * @returns {function} A function that, given `t`, returns an array of * interpolated values. * @private */ @@ -1804,7 +1864,7 @@ var map = function (arg) { * with the correct aspect ratio. * * @param {geo.geoBounds} bounds A desired bounds. - * @return {object} Multiplicative aspect ratio correction with x and y + * @returns {object} Multiplicative aspect ratio correction with x and y * values. * @private */ @@ -1977,7 +2037,7 @@ var map = function (arg) { * @param {boolean} noRangeLimit If falsy, ensure that the rotation is in the * range [0, 2*PI). If it is very close to zero, it is snapped to zero. * If true, the rotation can have any value. - * @return {number} the validated rotation + * @returns {number} the validated rotation * @private */ function fix_rotation(rotation, ignoreRotationFunc, noRangeLimit) { @@ -2020,6 +2080,8 @@ var map = function (arg) { * Specifically, the map's `maxBounds` can be shifted so that they lie no * further than the center of the bounds (rather than being forced to be * at the edge). + * @returns {geo.geoBounds} The adjusted bounds. This may be the same object + * passed in `bounds`. * @private */ function fix_bounds(bounds, rotation, delta, ignoreClampBounds) { @@ -2225,8 +2287,8 @@ var map = function (arg) { this.interactor(arg.interactor || mapInteractor({discreteZoom: m_discreteZoom})); } - if (arg.autoResize) { - $(window).resize(resizeSelf); + if (m_autoResize) { + $(window).on('resize', resizeSelf); } // attach attribution updates to layer events diff --git a/src/osmLayer.js b/src/osmLayer.js index f126f9a74d..2a2a3c14e5 100644 --- a/src/osmLayer.js +++ b/src/osmLayer.js @@ -56,8 +56,9 @@ module.exports = (function () { queue: this._queue, overlap: this._options.tileOverlap, scale: this._options.tileScale, - url: this._options.url(urlParams.x, urlParams.y, urlParams.level || 0, - this._options.subdomains) + url: this._options.url.call( + this, urlParams.x, urlParams.y, urlParams.level || 0, + this._options.subdomains) }); }.bind(this); }; diff --git a/src/registry.js b/src/registry.js index b66f94318b..cb94a440cc 100644 --- a/src/registry.js +++ b/src/registry.js @@ -280,6 +280,7 @@ util.createLayer = function (name, map, arg) { $.extend(true, options, arg); } layer = layers[name](options); + layer.layerName = name; layer._init(); return layer; } else { diff --git a/src/tileLayer.js b/src/tileLayer.js index efab5ab1c8..14fe593afa 100644 --- a/src/tileLayer.js +++ b/src/tileLayer.js @@ -446,8 +446,9 @@ module.exports = (function () { index: index, size: {x: this._options.tileWidth, y: this._options.tileHeight}, queue: this._queue, - url: this._options.url(urlParams.x, urlParams.y, urlParams.level || 0, - this._options.subdomains) + url: this._options.url.call( + this, urlParams.x, urlParams.y, urlParams.level || 0, + this._options.subdomains) }); }; diff --git a/tests/cases/map.js b/tests/cases/map.js index bcd2de31c1..608d58a4b4 100644 --- a/tests/cases/map.js +++ b/tests/cases/map.js @@ -139,6 +139,32 @@ describe('geo.core.map', function () { expect(m.unitsPerPixel()).toBeCloseTo(200000 * 16); expect(m.unitsPerPixel(4)).toBeCloseTo(200000); }); + it('animationQueue', function () { + mockAnimationFrame(); + var m = create_map(), queue = [], queue2 = [], + queue3 = [window.requestAnimationFrame(function () { })]; + expect(m.animationQueue()).toEqual([]); + expect(m.animationQueue()).not.toBe(queue); + expect(m.animationQueue(queue)).toBe(m); + expect(m.animationQueue()).toBe(queue); + m.scheduleAnimationFrame(function () { }); + expect(queue.length).toBe(2); + expect(m.animationQueue(queue2)).toBe(m); + expect(queue2.length).toBe(2); + expect(queue2).toEqual(queue); + expect(m.animationQueue(queue3)).toBe(m); + expect(queue3.length).toBe(2); + expect(queue3).not.toEqual(queue2); + unmockAnimationFrame(); + }); + it('autoResize', function () { + var m = create_map(); + expect(m.autoResize()).toBe(true); + expect(m.autoResize(false)).toBe(m); + expect(m.autoResize()).toBe(false); + expect(m.autoResize(true)).toBe(m); + expect(m.autoResize()).toBe(true); + }); it('gcs and ingcs', function () { var m = create_map(), units = m.unitsPerPixel(), bounds; var error = console.error; diff --git a/tests/cases/osmLayer.js b/tests/cases/osmLayer.js index c15ab6bd2e..312617b0e8 100644 --- a/tests/cases/osmLayer.js +++ b/tests/cases/osmLayer.js @@ -123,7 +123,7 @@ describe('geo.core.osmLayer', function () { describe('default osmLayer', function () { describe('html', function () { - var layer; + var layer, lastThis; it('creation', function () { map = create_map(); layer = map.createLayer('osm', {renderer: null, url: '/testdata/white.jpg'}); @@ -143,6 +143,19 @@ describe('geo.core.osmLayer', function () { waitForIt('.geo-tile-container', function () { return map.node().find('.geo-tile-container').length > 0; }); + it('tile function', function () { + map.deleteLayer(layer); + layer = map.createLayer('osm', {renderer: null, mapOpacity: 0.5, url: function (x, y, z) { + lastThis = this; + return '/testdata/white.jpg'; + }}); + }); + waitForIt('.geo-tile-container', function () { + return map.node().find('.geo-tile-container').length > 0; + }); + it('tile function test', function () { + expect(lastThis).toBe(layer); + }); /* The follow is a test of tileLayer as attached to a map. We don't * currently expose the tileLayer class directly to the createLayer * function, so some testing is done here */ diff --git a/tests/cases/tileLayer.js b/tests/cases/tileLayer.js index 428374b290..9b2b9fc357 100644 --- a/tests/cases/tileLayer.js +++ b/tests/cases/tileLayer.js @@ -957,14 +957,18 @@ describe('geo.tileLayer', function () { }); it('_getTile', function () { + var lastThis; var t, l = geo.tileLayer({ map: map(), tileWidth: 110, tileHeight: 120, - url: function (x, y, z) { return {x: x, y: y, level: z}; } + url: function (x, y, z) { + lastThis = this; + return {x: x, y: y, level: z}; + } }); - t = l._getTile({x: 1, y: 1, level: 0}, {x: 0, y: 0, level: 0}); + expect(lastThis).toBe(l); expect(t._url).toEqual({x: 0, y: 0, level: 0}); expect(t.size).toEqual({x: 110, y: 120}); expect(t.index).toEqual({x: 1, y: 1, level: 0});