From 7f38f22d8fccfc3c70759cdbb58228f79c275a93 Mon Sep 17 00:00:00 2001 From: Paul Spencer Date: Fri, 1 Aug 2008 18:25:28 +0000 Subject: [PATCH] Refactor backBuffer tile code out of generic Tile base class into Tile.Image to make it nicer when subclassing Tile for other needs. (Closes #1645) r=elemoine. git-svn-id: http://svn.openlayers.org/trunk/openlayers@7667 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf --- lib/OpenLayers/Tile.js | 132 +---------------------------------- lib/OpenLayers/Tile/Image.js | 121 +++++++++++++++++++++++++++++++- 2 files changed, 121 insertions(+), 132 deletions(-) diff --git a/lib/OpenLayers/Tile.js b/lib/OpenLayers/Tile.js index 9836d6d677..4a7401ceaf 100644 --- a/lib/OpenLayers/Tile.js +++ b/lib/OpenLayers/Tile.js @@ -79,38 +79,6 @@ OpenLayers.Tile = OpenLayers.Class({ * {Boolean} Is the tile loading? */ isLoading: false, - - /** - * Property: isBackBuffer - * {Boolean} Is this tile a back buffer tile? - */ - isBackBuffer: false, - - /** - * Property: lastRatio - * {Float} Used in transition code only. This is the previous ratio - * of the back buffer tile resolution to the map resolution. Compared - * with the current ratio to determine if zooming occurred. - */ - lastRatio: 1, - - /** - * Property: isFirstDraw - * {Boolean} Is this the first time the tile is being drawn? - * This is used to force resetBackBuffer to synchronize - * the backBufferTile with the foreground tile the first time - * the foreground tile loads so that if the user zooms - * before the layer has fully loaded, the backBufferTile for - * tiles that have been loaded can be used. - */ - isFirstDraw: true, - - /** - * Property: backBufferTile - * {} A clone of the tile used to create transition - * effects when the tile is moved or changes resolution. - */ - backBufferTile: null, /** TBD 3.0 -- remove 'url' from the list of parameters to the constructor. * there is no need for the base tile class to have a url. @@ -157,13 +125,6 @@ OpenLayers.Tile = OpenLayers.Class({ * Nullify references to prevent circular references and memory leaks. */ destroy:function() { - if (OpenLayers.Util.indexOf(this.layer.SUPPORTED_TRANSITIONS, - this.layer.transitionEffect) != -1) { - this.layer.events.unregister("loadend", this, this.resetBackBuffer); - this.events.unregister('loadend', this, this.resetBackBuffer); - } else { - this.events.unregister('loadend', this, this.showTile); - } this.layer = null; this.bounds = null; this.size = null; @@ -171,12 +132,6 @@ OpenLayers.Tile = OpenLayers.Class({ this.events.destroy(); this.events = null; - - /* clean up the backBufferTile if it exists */ - if (this.backBufferTile) { - this.backBufferTile.destroy(); - this.backBufferTile = null; - } }, /** @@ -221,50 +176,12 @@ OpenLayers.Tile = OpenLayers.Class({ // The only case where we *wouldn't* want to draw the tile is if the // tile is outside its layer's maxExtent. - var drawTile = (withinMaxExtent || this.layer.displayOutsideMaxExtent); - - if (OpenLayers.Util.indexOf(this.layer.SUPPORTED_TRANSITIONS, this.layer.transitionEffect) != -1) { - if (drawTile) { - //we use a clone of this tile to create a double buffer for visual - //continuity. The backBufferTile is used to create transition - //effects while the tile in the grid is repositioned and redrawn - if (!this.backBufferTile) { - this.backBufferTile = this.clone(); - this.backBufferTile.hide(); - // this is important. It allows the backBuffer to place itself - // appropriately in the DOM. The Image subclass needs to put - // the backBufferTile behind the main tile so the tiles can - // load over top and display as soon as they are loaded. - this.backBufferTile.isBackBuffer = true; - - // potentially end any transition effects when the tile loads - this.events.register('loadend', this, this.resetBackBuffer); - - // clear transition back buffer tile only after all tiles in - // this layer have loaded to avoid visual glitches - this.layer.events.register("loadend", this, this.resetBackBuffer); - } - // run any transition effects - this.startTransition(); - } else { - // if we aren't going to draw the tile, then the backBuffer should - // be hidden too! - if (this.backBufferTile) { - this.backBufferTile.clear(); - } - } - } else { - if (drawTile && this.isFirstDraw) { - this.events.register('loadend', this, this.showTile); - this.isFirstDraw = false; - } - } - this.shouldDraw = drawTile; - + this.shouldDraw = (withinMaxExtent || this.layer.displayOutsideMaxExtent); + //clear tile's contents and mark as not drawn this.clear(); - return drawTile; + return this.shouldDraw; }, /** @@ -335,49 +252,6 @@ OpenLayers.Tile = OpenLayers.Class({ topLeft.lat); return bounds; }, - - /** - * Method: startTransition - * Prepare the tile for a transition effect. To be - * implemented by subclasses. - */ - startTransition: function() {}, - - /** - * Method: resetBackBuffer - * Triggered by two different events, layer loadend, and tile loadend. - * In any of these cases, we check to see if we can hide the - * backBufferTile yet and update its parameters to match the - * foreground tile. - * - * Basic logic: - * - If the backBufferTile hasn't been drawn yet, reset it - * - If layer is still loading, show foreground tile but don't hide - * the backBufferTile yet - * - If layer is done loading, reset backBuffer tile and show - * foreground tile - */ - resetBackBuffer: function() { - this.showTile(); - if (this.backBufferTile && - (this.isFirstDraw || !this.layer.numLoadingTiles)) { - this.isFirstDraw = false; - // check to see if the backBufferTile is within the max extents - // before rendering it - var maxExtent = this.layer.maxExtent; - var withinMaxExtent = (maxExtent && - this.bounds.intersectsBounds(maxExtent, false)); - if (withinMaxExtent) { - this.backBufferTile.position = this.position; - this.backBufferTile.bounds = this.bounds; - this.backBufferTile.size = this.size; - this.backBufferTile.imageSize = this.layer.imageSize || this.size; - this.backBufferTile.imageOffset = this.layer.imageOffset; - this.backBufferTile.resolution = this.layer.getResolution(); - this.backBufferTile.renderTile(); - } - } - }, /** * Method: showTile diff --git a/lib/OpenLayers/Tile/Image.js b/lib/OpenLayers/Tile/Image.js index 713927f9bf..9fef2dcfde 100644 --- a/lib/OpenLayers/Tile/Image.js +++ b/lib/OpenLayers/Tile/Image.js @@ -37,13 +37,44 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { * the image will be hidden behind the frame. */ frame: null, - /** * Property: layerAlphaHack * {Boolean} True if the png alpha hack needs to be applied on the layer's div. */ layerAlphaHack: null, + + /** + * Property: isBackBuffer + * {Boolean} Is this tile a back buffer tile? + */ + isBackBuffer: false, + + /** + * Property: lastRatio + * {Float} Used in transition code only. This is the previous ratio + * of the back buffer tile resolution to the map resolution. Compared + * with the current ratio to determine if zooming occurred. + */ + lastRatio: 1, + + /** + * Property: isFirstDraw + * {Boolean} Is this the first time the tile is being drawn? + * This is used to force resetBackBuffer to synchronize + * the backBufferTile with the foreground tile the first time + * the foreground tile loads so that if the user zooms + * before the layer has fully loaded, the backBufferTile for + * tiles that have been loaded can be used. + */ + isFirstDraw: true, + + /** + * Property: backBufferTile + * {} A clone of the tile used to create transition + * effects when the tile is moved or changes resolution. + */ + backBufferTile: null, /** TBD 3.0 - reorder the parameters to the init function to remove * URL. the getUrl() function on the layer gets called on @@ -93,6 +124,15 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { this.layer.div.removeChild(this.frame); } this.frame = null; + + /* clean up the backBufferTile if it exists */ + if (this.backBufferTile) { + this.backBufferTile.destroy(); + this.backBufferTile = null; + } + + this.layer.events.unregister("loadend", this, this.resetBackBuffer); + OpenLayers.Tile.prototype.destroy.apply(this, arguments); }, @@ -135,8 +175,47 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { if (this.layer != this.layer.map.baseLayer && this.layer.reproject) { this.bounds = this.getBoundsFromBaseLayer(this.position); } - if (!OpenLayers.Tile.prototype.draw.apply(this, arguments)) { - return false; + var drawTile = OpenLayers.Tile.prototype.draw.apply(this, arguments); + + if (OpenLayers.Util.indexOf(this.layer.SUPPORTED_TRANSITIONS, this.layer.transitionEffect) != -1) { + if (drawTile) { + //we use a clone of this tile to create a double buffer for visual + //continuity. The backBufferTile is used to create transition + //effects while the tile in the grid is repositioned and redrawn + if (!this.backBufferTile) { + this.backBufferTile = this.clone(); + this.backBufferTile.hide(); + // this is important. It allows the backBuffer to place itself + // appropriately in the DOM. The Image subclass needs to put + // the backBufferTile behind the main tile so the tiles can + // load over top and display as soon as they are loaded. + this.backBufferTile.isBackBuffer = true; + + // potentially end any transition effects when the tile loads + this.events.register('loadend', this, this.resetBackBuffer); + + // clear transition back buffer tile only after all tiles in + // this layer have loaded to avoid visual glitches + this.layer.events.register("loadend", this, this.resetBackBuffer); + } + // run any transition effects + this.startTransition(); + } else { + // if we aren't going to draw the tile, then the backBuffer should + // be hidden too! + if (this.backBufferTile) { + this.backBufferTile.clear(); + } + } + } else { + if (drawTile && this.isFirstDraw) { + this.events.register('loadend', this, this.showTile); + this.isFirstDraw = false; + } + } + + if (!drawTile) { + return false; } if (this.isLoading) { @@ -150,6 +229,42 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { return this.renderTile(); }, + /** + * Method: resetBackBuffer + * Triggered by two different events, layer loadend, and tile loadend. + * In any of these cases, we check to see if we can hide the + * backBufferTile yet and update its parameters to match the + * foreground tile. + * + * Basic logic: + * - If the backBufferTile hasn't been drawn yet, reset it + * - If layer is still loading, show foreground tile but don't hide + * the backBufferTile yet + * - If layer is done loading, reset backBuffer tile and show + * foreground tile + */ + resetBackBuffer: function() { + this.showTile(); + if (this.backBufferTile && + (this.isFirstDraw || !this.layer.numLoadingTiles)) { + this.isFirstDraw = false; + // check to see if the backBufferTile is within the max extents + // before rendering it + var maxExtent = this.layer.maxExtent; + var withinMaxExtent = (maxExtent && + this.bounds.intersectsBounds(maxExtent, false)); + if (withinMaxExtent) { + this.backBufferTile.position = this.position; + this.backBufferTile.bounds = this.bounds; + this.backBufferTile.size = this.size; + this.backBufferTile.imageSize = this.layer.imageSize || this.size; + this.backBufferTile.imageOffset = this.layer.imageOffset; + this.backBufferTile.resolution = this.layer.getResolution(); + this.backBufferTile.renderTile(); + } + } + }, + /** * Method: renderTile * Internal function to actually initialize the image tile,