From ef85f43d21e58f7a8d840e091097b0e10dffa82c Mon Sep 17 00:00:00 2001 From: ahocevar Date: Thu, 26 Jan 2012 01:24:11 +0100 Subject: [PATCH 1/9] A tile queue that can be aborted. This saves server requests, and because we use OpenLayers.Animation, setting img.src on a tile should not freeze iOS any more, so we can hopefully get rid of scheduleMoveGriddedTiles. --- examples/mobile-wmts-vienna.html | 3 +- examples/mobile-wmts-vienna.js | 2 - lib/OpenLayers/Layer/Grid.js | 274 ++++++++---------- tests/Layer/ArcGIS93Rest.html | 5 + tests/Layer/Grid.html | 19 +- tests/Layer/MapServer.html | 5 + tests/Layer/WMS.html | 5 + tests/Layer/WrapDateLine.html | 5 + tests/deprecated/Layer/MapServer/Untiled.html | 5 + 9 files changed, 165 insertions(+), 158 deletions(-) diff --git a/examples/mobile-wmts-vienna.html b/examples/mobile-wmts-vienna.html index 280f66ce74..11e1ee995e 100644 --- a/examples/mobile-wmts-vienna.html +++ b/examples/mobile-wmts-vienna.html @@ -6,8 +6,8 @@ + -

City of Vienna WMTS for Desktop and Mobile Devices

@@ -22,6 +22,7 @@ functionality and uses the Geolocate control.

+ diff --git a/examples/mobile-wmts-vienna.js b/examples/mobile-wmts-vienna.js index 692b86afe2..4257f7429b 100644 --- a/examples/mobile-wmts-vienna.js +++ b/examples/mobile-wmts-vienna.js @@ -152,7 +152,6 @@ var map; var defaults = { requestEncoding: "REST", matrixSet: "google3857", - buffer: 4, attribution: 'Datenquelle: Stadt Wien - data.wien.gv.at' }; var doc = request.responseText, @@ -182,7 +181,6 @@ var map; requestEncoding: "REST", matrixSet: "google3857", tileFullExtent: extent, - buffer: 4, attribution: 'Datenquelle: Stadt Wien - data.wien.gv.at' }; fmzk = new OpenLayers.Layer.WMTS(OpenLayers.Util.applyDefaults({ diff --git a/lib/OpenLayers/Layer/Grid.js b/lib/OpenLayers/Layer/Grid.js index 0a1c2d8220..1e5b0c9d89 100644 --- a/lib/OpenLayers/Layer/Grid.js +++ b/lib/OpenLayers/Layer/Grid.js @@ -97,13 +97,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { */ numLoadingTiles: 0, - /** - * APIProperty: tileLoadingDelay - * {Integer} - Number of milliseconds before we shift and load - * tiles. Default is 100. - */ - tileLoadingDelay: 100, - /** * Property: serverResolutions * {Array(Number}} This property is documented in subclasses as @@ -112,10 +105,16 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { serverResolutions: null, /** - * Property: timerId - * {Number} - The id of the tileLoadingDelay timer. + * Property: tileLoopId + * {Number} - The id of the animation. */ - timerId: null, + tileLoopId: null, + + /** + * Property: tileOperations + * {Array(Object)} Pending tile operations. + */ + tileOperations: null, /** * Property: backBuffer @@ -152,7 +151,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { * flash effects caused by tile animation. */ backBufferTimerId: null, - + /** * Register a listener for a particular event with the following syntax: * (code) @@ -187,10 +186,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { OpenLayers.Layer.HTTPRequest.prototype.initialize.apply(this, arguments); this.grid = []; - - this._moveGriddedTiles = OpenLayers.Function.bind( - this.moveGriddedTiles, this - ); + this.tileOperations = []; }, /** @@ -201,10 +197,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { * map - {} The map. */ removeMap: function(map) { - if(this.timerId != null) { - window.clearTimeout(this.timerId); - this.timerId = null; - } + this.abortTileOperations(); if(this.backBufferTimerId !== null) { window.clearTimeout(this.backBufferTimerId); this.backBufferTimerId = null; @@ -230,20 +223,20 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { * destroy() on each of them to kill circular references */ clearGrid:function() { + this.abortTileOperations(); if (this.grid) { for(var iRow=0, len=this.grid.length; iRow} + */ + destroyTile: function(tile) { + for (var i=this.tileOperations.length-1; i>=0; --i) { + if (this.tileOperations[i].scope === tile) { + this.tileOperations.splice(i, 1); + } + } + this.removeTileMonitoringHooks(tile); + tile.destroy(); + }, /** * Method: getServerResolution @@ -565,24 +619,10 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { */ moveByPx: function(dx, dy) { if (!this.singleTile) { - this.scheduleMoveGriddedTiles(); + this.moveGriddedTiles(); } }, - /** - * Method: scheduleMoveGriddedTiles - * Schedule the move of tiles. - */ - scheduleMoveGriddedTiles: function() { - if (this.timerId != null) { - window.clearTimeout(this.timerId); - } - this.timerId = window.setTimeout( - this._moveGriddedTiles, - this.tileLoadingDelay - ); - }, - /** * APIMethod: setTileSize * Check if we are in singleTile mode and if so, set the size as a ratio @@ -776,7 +816,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { var layerContainerDivLeft = parseInt(this.map.layerContainerDiv.style.left); var layerContainerDivTop = parseInt(this.map.layerContainerDiv.style.top); - + var tileData = [], center = this.map.getCenter(); do { var row = this.grid[rowidx++]; if (!row) { @@ -810,6 +850,12 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { } else { tile.moveTo(tileBounds, px, false); } + var tileCenter = tileBounds.getCenterLonLat(); + tileData.push({ + tile: tile, + distance: Math.pow(tileCenter.lon - center.lon, 2) + + Math.pow(tileCenter.lat - center.lat, 2) + }); tileoffsetlon += tilelon; tileoffsetx += this.tileSize.w; @@ -828,7 +874,12 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { this.gridResolution = this.getServerResolution(); //now actually draw the tiles - this.spiralTileLoad(); + tileData.sort(function(a, b) { + return a.distance - b.distance; + }); + for (var i=0, ii=tileData.length; i= 0) && - (testCell < this.grid[0].length) && (testCell >= 0)) { - tile = this.grid[testRow][testCell]; - } - - if ((tile != null) && (!tile.queued)) { - //add tile to beginning of queue, mark it as queued. - tileQueue.unshift(tile); - tile.queued = true; - - //restart the directions counter and take on the new coords - directionsTried = 0; - iRow = testRow; - iCell = testCell; - } else { - //need to try to load a tile in a different direction - direction = (direction + 1) % 4; - directionsTried++; - } - } - - // now we go through and draw the tiles in forward order - for(var i=0, len=tileQueue.length; i} The added OpenLayers.Tile */ addTile: function(bounds, position) { + var that = this; + var options = OpenLayers.Util.extend({ + draw: function() { + // clear immediately + this.clear(); + // draw in an animation frame - can be aborted + that.addTileOperation(that.tileClass.prototype.draw, this); + } + }, this.tileOptions); return new this.tileClass(this, position, bounds, null, - this.tileSize, this.tileOptions); + this.tileSize, options); }, /** @@ -993,37 +980,32 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { * Method: moveGriddedTiles */ moveGriddedTiles: function() { - var shifted = true; var buffer = this.buffer || 1; var scale = this.getResolutionScale(); - var tlLayer = this.grid[0][0].position.clone(); - tlLayer.x *= scale; - tlLayer.y *= scale; - tlLayer = tlLayer.add(parseInt(this.div.style.left, 10), - parseInt(this.div.style.top, 10)); - var offsetX = parseInt(this.map.layerContainerDiv.style.left); - var offsetY = parseInt(this.map.layerContainerDiv.style.top); - var tlViewPort = tlLayer.add(offsetX, offsetY); - var tileSize = { - w: this.tileSize.w * scale, - h: this.tileSize.h * scale - }; - if (tlViewPort.x > -tileSize.w * (buffer - 1)) { - this.shiftColumn(true); - } else if (tlViewPort.x < -tileSize.w * buffer) { - this.shiftColumn(false); - } else if (tlViewPort.y > -tileSize.h * (buffer - 1)) { - this.shiftRow(true); - } else if (tlViewPort.y < -tileSize.h * buffer) { - this.shiftRow(false); - } else { - shifted = false; - } - if (shifted) { - // we may have other row or columns to shift, schedule it - // with a setTimeout, to give the user a chance to sneak - // in moveTo's - this.timerId = window.setTimeout(this._moveGriddedTiles, 0); + while(true) { + var tlLayer = this.grid[0][0].position.clone(); + tlLayer.x *= scale; + tlLayer.y *= scale; + tlLayer = tlLayer.add(parseInt(this.div.style.left, 10), + parseInt(this.div.style.top, 10)); + var offsetX = parseInt(this.map.layerContainerDiv.style.left); + var offsetY = parseInt(this.map.layerContainerDiv.style.top); + var tlViewPort = tlLayer.add(offsetX, offsetY); + var tileSize = { + w: this.tileSize.w * scale, + h: this.tileSize.h * scale + }; + if (tlViewPort.x > -tileSize.w * (buffer - 1)) { + this.shiftColumn(true); + } else if (tlViewPort.x < -tileSize.w * buffer) { + this.shiftColumn(false); + } else if (tlViewPort.y > -tileSize.h * (buffer - 1)) { + this.shiftRow(true); + } else if (tlViewPort.y < -tileSize.h * buffer) { + this.shiftRow(false); + } else { + break; + } } }, @@ -1113,8 +1095,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { var row = this.grid.pop(); for (var i=0, l=row.length; iwindow.alert = oldAlert;