From c8564838bc0c799690ee0930f145476d3c296729 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Fri, 28 Dec 2012 10:51:23 +0100 Subject: [PATCH 1/2] When the resolution does not change, remove backbuffer tile by tile This change introduces a new 'replace' mode for tile transitions: when the resolution does not change, which happens when mergeNewParams is called, the tile will be marked with the .olTileReplace class. If this class sets the tile's imgDiv display to 'none', the backbuffer for the tile will immediately be removed when the tile is loaded. --- lib/OpenLayers/Layer/Grid.js | 36 ++++++++++++++++++++++++++++++++++-- tests/Layer/Grid.html | 28 +++++++++++++++++++++++++++- theme/default/style.css | 5 +++++ 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/lib/OpenLayers/Layer/Grid.js b/lib/OpenLayers/Layer/Grid.js index edc9bc3ba5..8d5fa2b756 100644 --- a/lib/OpenLayers/Layer/Grid.js +++ b/lib/OpenLayers/Layer/Grid.js @@ -336,6 +336,21 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { OpenLayers.Layer.HTTPRequest.prototype.destroy.apply(this, arguments); }, + /** + * APIMethod: mergeNewParams + * Refetches tiles with new params merged, keeping a backbuffer. Each + * loading new tile will have a css class of '.olTileReplacing'. If a + * stylesheet applies a 'display: none' style to that class, any fade-in + * transition will not apply, and backbuffers for each tile will be removed + * as soon as the tile is loaded. + * + * Parameters: + * newParams - {Object} + * + * Returns: + * redrawn: {Boolean} whether the layer was actually redrawn. + */ + /** * Method: clearGrid * Go through and remove all tiles from the grid, calling @@ -489,7 +504,8 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { }); if(forceReTile) { - if(zoomChanged && this.transitionEffect === 'resize') { + if(zoomChanged && (this.transitionEffect === 'resize' || + this.gridResolution === resolution)) { this.applyBackBuffer(resolution); } this.initGriddedTiles(bounds); @@ -692,6 +708,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { markup._j = j; markup._w = tile.size.w; markup._h = tile.size.h; + markup.id = tile.id + '_bb'; backBuffer.appendChild(markup); } } @@ -1053,6 +1070,8 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { */ addTileMonitoringHooks: function(tile) { + var replacingCls = 'olTileReplacing'; + tile.onLoadStart = function() { //if that was first tile then trigger a 'loadstart' on the layer if (this.loading === false) { @@ -1061,14 +1080,27 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { } this.events.triggerEvent("tileloadstart", {tile: tile}); this.numLoadingTiles++; + if (this.backBuffer && this.gridResolution === this.backBufferResolution) { + OpenLayers.Element.addClass(tile.imgDiv, replacingCls); + } }; tile.onLoadEnd = function(evt) { this.numLoadingTiles--; + var aborted = evt.type === 'unload'; this.events.triggerEvent("tileloaded", { tile: tile, - aborted: evt.type === "unload" + aborted: aborted }); + if (!aborted && this.backBuffer && this.gridResolution === this.backBufferResolution) { + if (OpenLayers.Element.getStyle(tile.imgDiv, 'display') === 'none') { + var bufferTile = document.getElementById(tile.id + '_bb'); + if (bufferTile) { + bufferTile.parentNode.removeChild(bufferTile); + } + } + OpenLayers.Element.removeClass(tile.imgDiv, replacingCls); + } //if that was the last tile, then trigger a 'loadend' on the layer if (this.numLoadingTiles === 0) { this.loading = false; diff --git a/tests/Layer/Grid.html b/tests/Layer/Grid.html index d05769ed12..ce36c72673 100644 --- a/tests/Layer/Grid.html +++ b/tests/Layer/Grid.html @@ -526,7 +526,8 @@ } } } - } + }, + imgDiv: {className: ''} } g_registered = {}; @@ -1118,6 +1119,31 @@ map.destroy(); } + + function test_backbuffer_replace(t) { + t.plan(6); + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS('', '../../img/blank.gif'); + map.addLayer(layer); + map.zoomToMaxExtent(); + + t.delay_call(1, function() { + layer.mergeNewParams({foo: 'bar'}); + var tile = layer.grid[1][1]; + t.ok(OpenLayers.Element.hasClass(tile.imgDiv, 'olTileReplacing'), 'tile is marked for being replaced'); + t.ok(document.getElementById(tile.id + '_bb'), 'backbuffer created for tile'); + tile.onImageLoad(); + t.ok(!OpenLayers.Element.hasClass(tile.imgDiv, 'olTileReplacing'), 'tile replaced, no longer marked'); + t.ok(!document.getElementById(tile.id + '_bb'), 'backbuffer removed for tile'); + + layer.mergeNewParams({foo: 'baz'}); + tile = layer.grid[1][1]; + tile.imgDiv.style.display = 'block'; + tile.onImageLoad(); + t.ok(!OpenLayers.Element.hasClass(tile.imgDiv, 'olTileReplacing'), 'tile replaced, no longer marked'); + t.ok(document.getElementById(tile.id + '_bb'), 'backbuffer not removed for visible tile'); + }); + } function test_singleTile_move_and_zoom(t) { diff --git a/theme/default/style.css b/theme/default/style.css index ed8cef75ce..a3b75ba519 100644 --- a/theme/default/style.css +++ b/theme/default/style.css @@ -487,6 +487,11 @@ a.olControlZoomOut { transition: opacity 0.2s linear; } +/* when replacing tiles, do not show tile and backbuffer at the same time */ +.olTileImage.olTileReplacing { + display: none; +} + /* override any max-width image settings (e.g. bootstrap.css) */ img.olTileImage { max-width: none; From f0db21f9c9f7d98067923f7ed519214933012ad3 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Mon, 7 Jan 2013 18:16:23 +0100 Subject: [PATCH 2/2] Fixing tests --- tests/Layer/Grid.html | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Layer/Grid.html b/tests/Layer/Grid.html index ce36c72673..2bdd5d79f6 100644 --- a/tests/Layer/Grid.html +++ b/tests/Layer/Grid.html @@ -1132,12 +1132,17 @@ var tile = layer.grid[1][1]; t.ok(OpenLayers.Element.hasClass(tile.imgDiv, 'olTileReplacing'), 'tile is marked for being replaced'); t.ok(document.getElementById(tile.id + '_bb'), 'backbuffer created for tile'); + // simulate a css declaration where '.olTileReplacing' sets display + // to none. + tile.imgDiv.style.display = 'none'; tile.onImageLoad(); t.ok(!OpenLayers.Element.hasClass(tile.imgDiv, 'olTileReplacing'), 'tile replaced, no longer marked'); t.ok(!document.getElementById(tile.id + '_bb'), 'backbuffer removed for tile'); layer.mergeNewParams({foo: 'baz'}); tile = layer.grid[1][1]; + // simulate a css declaration where '.olTileReplacing' does not set + // display to none. tile.imgDiv.style.display = 'block'; tile.onImageLoad(); t.ok(!OpenLayers.Element.hasClass(tile.imgDiv, 'olTileReplacing'), 'tile replaced, no longer marked');