New TileManager

This removes all tile queueing/loading specific code from Layer.Grid
and creates a new class that manages tile loading and caching.
This commit is contained in:
ahocevar
2012-11-29 14:52:53 -06:00
parent 2ee362a79b
commit 80fa251649
16 changed files with 499 additions and 311 deletions

View File

@@ -197,20 +197,12 @@ OpenLayers.Layer.Bing = OpenLayers.Class(OpenLayers.Layer.XYZ, {
res.zoomMax + 1 - res.zoomMin, this.numZoomLevels
)
}, true);
if (!this.isBaseLayer) {
this.redraw();
}
this.updateAttribution();
},
/**
* Method: drawTilesFromQueue
* Draws tiles from the tileQueue, and unqueues the tiles
*/
drawTilesFromQueue: function() {
// don't start working on the queue before we have a url from initLayer
if (this.url) {
OpenLayers.Layer.XYZ.prototype.drawTilesFromQueue.apply(this, arguments);
}
},
/**
* Method: getURL
*
@@ -218,6 +210,9 @@ OpenLayers.Layer.Bing = OpenLayers.Class(OpenLayers.Layer.XYZ, {
* bounds - {<OpenLayers.Bounds>}
*/
getURL: function(bounds) {
if (!this.url) {
return;
}
var xyz = this.getXYZ(bounds), x = xyz.x, y = xyz.y, z = xyz.z;
var quadDigits = [];
for (var i = z; i > 0; --i) {

View File

@@ -113,14 +113,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
*/
numLoadingTiles: 0,
/**
* APIProperty: tileLoadingDelay
* {Integer} Number of milliseconds before we shift and load
* tiles when panning. Ignored if <OpenLayers.Animation.isNative> is
* true. Default is 85.
*/
tileLoadingDelay: 85,
/**
* Property: serverResolutions
* {Array(Number}} This property is documented in subclasses as
@@ -128,32 +120,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
*/
serverResolutions: null,
/**
* Property: moveTimerId
* {Number} The id of the <deferMoveGriddedTiles> timer.
*/
moveTimerId: null,
/**
* Property: deferMoveGriddedTiles
* {Function} A function that defers execution of <moveGriddedTiles> by
* <tileLoadingDelay>. If <OpenLayers.Animation.isNative> is true, this
* is null and unused.
*/
deferMoveGriddedTiles: null,
/**
* Property: tileQueueId
* {Number} The id of the <drawTilesFromQueue> animation.
*/
tileQueueId: null,
/**
* Property: tileQueue
* {Array(<OpenLayers.Tile>)} Tiles queued for drawing.
*/
tileQueue: null,
/**
* Property: loading
* {Boolean} Indicates if tiles are being loaded.
@@ -241,26 +207,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
*/
className: null,
/**
* Property: tileCache
* {Object} Cached image elements, keyed by URL.
*/
tileCache: null,
/**
* Property: tileCacheIndex
* {Array<String>} URLs of cached tiles; first entry is least recently
* used.
*/
tileCacheIndex: null,
/**
* APIProperty: tileCacheSize
* {Number} Number of image elements to keep referenced for fast reuse.
* Default is 128 per layer.
*/
tileCacheSize: 128,
/**
* Register a listener for a particular event with the following syntax:
* (code)
@@ -275,6 +221,9 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
* element - {DOMElement} A reference to layer.events.element.
*
* Supported event types:
* addtile - Triggered when a tile is added to this layer. Listeners receive
* an object as first argument, which has a tile property that
* references the tile that has been added.
* tileloadstart - Triggered when a tile starts loading. Listeners receive
* an object as first argument, which has a tile property that
* references the tile that starts loading.
@@ -289,6 +238,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
* still hidden) if a tile failed to load. Listeners receive an object
* as first argument, which has a tile property that references the
* tile that could not be loaded.
* retile - Triggered when the layer recreates its tile grid.
*/
/**
@@ -342,13 +292,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
'olLayerGrid';
}
if (!OpenLayers.Animation.isNative) {
this.deferMoveGriddedTiles = OpenLayers.Function.bind(function() {
this.moveGriddedTiles(true);
this.moveTimerId = null;
}, this);
}
this.rowSign = this.tileOriginCorner.substr(0, 1) === "t" ? 1 : -1;
},
@@ -375,7 +318,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
window.clearTimeout(this.moveTimerId);
this.moveTimerId = null;
}
this.clearTileQueue();
if(this.backBufferTimerId !== null) {
window.clearTimeout(this.backBufferTimerId);
this.backBufferTimerId = null;
@@ -392,7 +334,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
this.grid = null;
this.tileSize = null;
this.tileCache = null;
OpenLayers.Layer.HTTPRequest.prototype.destroy.apply(this, arguments);
},
@@ -402,7 +343,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
* destroy() on each of them to kill circular references
*/
clearGrid:function() {
this.clearTileQueue();
if (this.grid) {
for(var iRow=0, len=this.grid.length; iRow<len; iRow++) {
var row = this.grid[iRow];
@@ -450,8 +390,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
// same for backbuffer and tile queue
obj.backBuffer = null;
obj.backBufferTimerId = null;
obj.tileQueue = [];
obj.tileQueueId = null;
obj.loading = false;
obj.moveTimerId = null;
@@ -599,92 +537,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
return data;
},
/**
* Method: queueTileDraw
* Adds a tile to the animation queue that will draw it.
*
* Parameters:
* evt - {Object} Listener argument of the tile's beforedraw event
*/
queueTileDraw: function(evt) {
var tile = evt.object;
var queued = false;
if (this.async || !this.url ||
!this.tileCache[this.getURL(tile.bounds)]) {
// queue only if not in tileCache already
if (!~OpenLayers.Util.indexOf(this.tileQueue, tile)) {
// add to queue only if not in queue already
this.tileQueue.push(tile);
}
queued = true;
if (!this.tileQueueId) {
this.tileQueueId = OpenLayers.Animation.start(
OpenLayers.Function.bind(this.drawTilesFromQueue, this),
null, this.div
);
}
}
return !queued;
},
/**
* Method: drawTilesFromQueue
* Draws tiles from the tileQueue, and unqueues the tiles
*/
drawTilesFromQueue: function() {
var numUrls = OpenLayers.Util.isArray(this.url) ? this.url.length : 1;
//TODO instead of using 2 * urls, we could keep track of the hosts used
// by all grid layers, and use a number that just saturates the number
// of parallel requests the browser can send
while (this.numLoadingTiles < 2 * numUrls) {
if (this.tileQueue.length === 0) {
this.clearTileQueue();
break;
}
this.tileQueue.shift().draw(true);
}
},
/**
* Method: manageTileCache
* Adds, updates, removes and fetches cache entries.
*
* Parameters:
* evt - {Object} Listener argument of the tile's loadstart event
*/
manageTileCache: function(evt) {
var tile = evt.object;
if (this.tileCache[tile.url]) {
tile.imgDiv = this.tileCache[tile.url];
OpenLayers.Util.removeItem(this.tileCacheIndex, tile.url);
this.tileCacheIndex.push(tile.url);
tile.positionTile();
this.div.appendChild(tile.imgDiv);
} else {
tile.events.register('loadend', this, function loadend() {
tile.events.unregister('loadend', this, loadend);
if (!this.tileCache[tile.url]) {
if (this.tileCacheIndex.length >= this.tileCacheSize) {
delete this.tileCache[this.tileCacheIndex[0]];
this.tileCacheIndex.shift();
}
this.tileCache[tile.url] = tile.imgDiv;
this.tileCacheIndex.push(tile.url);
}
});
}
},
/**
* Method: clearTileQueue
* Clears the animation queue
*/
clearTileQueue: function() {
window.clearInterval(this.tileQueueId);
this.tileQueueId = null;
this.tileQueue = [];
},
/**
* Method: destroyTile
*
@@ -843,10 +695,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
this.div.removeChild(this.backBuffer);
this.backBuffer = null;
this.backBufferResolution = null;
if(this.backBufferTimerId !== null) {
window.clearTimeout(this.backBufferTimerId);
this.backBufferTimerId = null;
}
}
},
@@ -914,7 +762,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
* bounds - {<OpenLayers.Bounds>}
*/
initSingleTile: function(bounds) {
this.clearTileQueue();
this.events.triggerEvent("retile");
//determine new tile bounds
var center = bounds.getCenterLonLat();
@@ -1047,7 +895,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
* bounds - {<OpenLayers.Bounds>}
*/
initGriddedTiles:function(bounds) {
this.clearTileQueue();
this.events.triggerEvent("retile");
// work out mininum number of rows and columns; this is the number of
// tiles required to cover the viewport plus at least one for panning
@@ -1126,8 +974,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
//shave off exceess rows and colums
this.removeExcessTiles(rowidx, colidx);
var resolution = this.getServerResolution(),
immediately = resolution === this.gridResolution;
var resolution = this.getServerResolution();
// store the resolution of the grid
this.gridResolution = resolution;
@@ -1136,7 +983,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
return a.distance - b.distance;
});
for (var i=0, ii=tileData.length; i<ii; ++i) {
tileData[i].tile.draw(immediately);
tileData[i].tile.draw();
}
},
@@ -1167,11 +1014,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
var tile = new this.tileClass(
this, position, bounds, null, this.tileSize, this.tileOptions
);
tile.events.on({
beforedraw: this.queueTileDraw,
loadstart: this.manageTileCache,
scope: this
});
this.events.triggerEvent("addtile", {tile: tile});
return tile;
},
@@ -1202,7 +1045,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
aborted: evt.type === "unload"
});
//if that was the last tile, then trigger a 'loadend' on the layer
if (this.tileQueue.length === 0 && this.numLoadingTiles === 0) {
if (this.numLoadingTiles === 0) {
this.loading = false;
this.events.triggerEvent("loadend");
if(this.backBuffer) {
@@ -1255,21 +1098,8 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
/**
* Method: moveGriddedTiles
*
* Parameter:
* deferred - {Boolean} true if this is a deferred call that should not
* be delayed.
*/
moveGriddedTiles: function(deferred) {
if (!deferred && !OpenLayers.Animation.isNative) {
if (this.moveTimerId != null) {
window.clearTimeout(this.moveTimerId);
}
this.moveTimerId = window.setTimeout(
this.deferMoveGriddedTiles, this.tileLoadingDelay
);
return;
}
moveGriddedTiles: function() {
var buffer = this.buffer + 1;
while(true) {
var tlTile = this.grid[0][0];

View File

@@ -193,22 +193,20 @@ OpenLayers.Tile = OpenLayers.Class({
* is to call <clear> and return the result from <shouldDraw>.
*
* Parameters:
* immediately - {Boolean} When e.g. drawing was aborted by returning false
* from a *beforedraw* listener, the queue manager needs to pass true,
* so the tile will not be cleared and immediately be drawn. Otherwise,
* the tile will be cleared and a *beforedraw* event will be fired.
* force - {Boolean} No beforedraw event will be fired.
*
* Returns:
* {Boolean} Whether or not the tile should actually be drawn.
* {Boolean} Whether or not the tile should actually be drawn. Retruns null
* if a beforedraw listener returned false.
*/
draw: function(immediately) {
if (!immediately) {
draw: function(force) {
if (!force) {
//clear tile's contents and mark as not drawn
this.clear();
}
var draw = this.shouldDraw();
if (draw && !immediately) {
draw = this.events.triggerEvent("beforedraw") !== false;
if (draw && !force && this.events.triggerEvent("beforedraw") === false) {
draw = null;
}
return draw;
},

View File

@@ -146,11 +146,12 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, {
* Check that a tile should be drawn, and draw it.
*
* Returns:
* {Boolean} Was a tile drawn?
* {Boolean} Was a tile drawn? Or null if a beforedraw listener returned
* false.
*/
draw: function() {
var drawn = OpenLayers.Tile.prototype.draw.apply(this, arguments);
if (drawn) {
var shouldDraw = OpenLayers.Tile.prototype.draw.apply(this, arguments);
if (shouldDraw) {
// The layer's reproject option is deprecated.
if (this.layer != this.layer.map.baseLayer && this.layer.reproject) {
// getBoundsFromBaseLayer is defined in deprecated.js.
@@ -158,17 +159,17 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, {
}
if (this.isLoading) {
//if we're already loading, send 'reload' instead of 'loadstart'.
this._loadEvent = "reload";
this._loadEvent = "reload";
} else {
this.isLoading = true;
this._loadEvent = "loadstart";
}
this.positionTile();
this.renderTile();
} else {
} else if (shouldDraw === false) {
this.unload();
}
return drawn;
return shouldDraw;
},
/**
@@ -287,9 +288,11 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, {
this.events.triggerEvent(this._loadEvent);
var img = this.getImage();
if (this.url && img.getAttribute("src") == this.url) {
this.onImageLoad();
this._loadTimeout = window.setTimeout(
OpenLayers.Function.bind(this.onImageLoad, this), 0
);
} else {
OpenLayers.Event.stopObservingElement(img);
this.stopLoading();
if (this.crossOriginKeyword) {
img.removeAttribute("crossorigin");
}
@@ -328,7 +331,7 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, {
} else {
// Remove reference to the image, and leave it to the browser's
// caching and garbage collection.
OpenLayers.Event.stopObservingElement(this.imgDiv);
this.stopLoading();
this.imgDiv = null;
if (img.parentNode) {
img.parentNode.removeChild(img);
@@ -378,7 +381,7 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, {
*/
onImageLoad: function() {
var img = this.imgDiv;
OpenLayers.Event.stopObservingElement(img);
this.stopLoading();
img.style.visibility = 'inherit';
img.style.opacity = this.layer.opacity;
this.isLoading = false;
@@ -409,6 +412,16 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, {
}
}
},
/**
* Method: stopLoading
* Stops a loading sequence so <onImageLoad> won't be executed.
*/
stopLoading: function() {
OpenLayers.Event.stopObservingElement(this.imgDiv);
window.clearTimeout(this._loadTimeout);
delete this._loadTimeout;
},
/**
* APIMethod: getCanvasContext

View File

@@ -0,0 +1,334 @@
/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for
* full list of contributors). Published under the 2-clause BSD license.
* See license.txt in the OpenLayers distribution or repository for the
* full text of the license. */
/**
* @requires OpenLayers/Layer/Grid.js
* @requires OpenLayers/Util.js
* @requires OpenLayers/BaseTypes.js
* @requires OpenLayers/BaseTypes/Element.js
*/
/**
* Class: OpenLayers.TileManager
* Provides queueing of image requests and caching of image elements.
*
* Queueing avoids unnecessary image requests while changing zoom levels
* quickly, and helps improve dragging performance on mobile devices that show
* a lag in dragging when loading of new images start. <zoomDelay> and
* <moveDelay> are the configuration options to control this behavior.
*
* Caching avoids setting the src on image elements for images that have already
* been used. A TileManager instance can have a private cache (when configured
* with a <cacheSize>), or share a cache with other instances, in which case the
* cache size can be controlled by adjusting <OpenLayers.TileManager.cacheSize>.
*/
OpenLayers.TileManager = OpenLayers.Class({
/**
* APIProperty: map
* {<OpenLayers.Map>} The map to manage tiles on.
*/
map: null,
/**
* APIProperty: cacheSize
* {Number} Number of image elements to keep referenced in this instance's
* private cache for fast reuse. If not set, this instance will use the
* shared cache. To configure the shared cache size, set
* <OpenLayers.TileManager.cacheSize>.
*/
cacheSize: null,
/**
* APIProperty: moveDelay
* {Number} Delay in milliseconds after a map's move event before loading
* tiles. Default is 100.
*/
moveDelay: 100,
/**
* APIProperty: zoomDelay
* {Number} Delay in milliseconds after a map's zoomend event before loading
* tiles. Default is 200.
*/
zoomDelay: 200,
/**
* Property: tileQueueId
* {Number} The id of the <drawTilesFromQueue> animation.
*/
tileQueueId: null,
/**
* Property: tileQueue
* {Array(<OpenLayers.Tile>)} Tiles queued for drawing.
*/
tileQueue: null,
/**
* Property: tileCache
* {Object} Cached image elements, keyed by URL. This is shared among all
* TileManager instances, unless <cacheSize> is set on the instance.
*/
tileCache: {},
/**
* Property: tileCacheIndex
* {Array<String>} URLs of cached tiles; first entry is least recently
* used. This is shared among all TileManager instances, unless
* <cacheSize> is set on the instance.
*/
tileCacheIndex: [],
/**
* Constructor: OpenLayers.TileManager
* Constructor for a new <OpenLayers.TileManager> instance.
*
* Parameters:
* options - {Object} Configuration for this instance.
*
* Required options:
* map - {<OpenLayers.Map>} The map to manage tiles on.
*/
initialize: function(options) {
OpenLayers.Util.extend(this, options);
this.tileQueue = [];
if (this.cacheSize == null) {
this.cacheSize = OpenLayers.TileManager.cacheSize;
} else {
this.tileCache = {};
this.tileCacheIndex = [];
}
var map = this.map;
for (var i=0, ii=map.layers.length; i<ii; ++i) {
this.addLayer({layer: map.layers[i]});
}
this.map.events.on({
move: this.move,
zoomend: this.zoomEnd,
addlayer: this.addLayer,
removelayer: this.removeLayer,
scope: this
});
},
/**
* Method: move
* Handles the map's move event
*/
move: function() {
this.updateTimeout(this.moveDelay);
},
/**
* Method: zoomEnd
* Handles the map's zoomEnd event
*/
zoomEnd: function() {
this.updateTimeout(this.zoomDelay);
},
/**
* Method: addLayer
* Handles the map's addlayer event
*
* Parameters:
* evt - {Object} The listener argument
*/
addLayer: function(evt) {
var layer = evt.layer;
if (layer instanceof OpenLayers.Layer.Grid) {
layer.events.on({
addtile: this.addTile,
retile: this.clearTileQueue,
scope: this
});
var i, j, tile;
for (i=layer.grid.length-1; i>=0; --i) {
for (j=layer.grid[i].length-1; j>=0; --j) {
tile = layer.grid[i][j];
this.addTile({tile: tile});
if (tile.url) {
this.manageTileCache({object: tile});
}
}
}
}
},
/**
* Method: addLayer
* Handles the map's removelayer event
*
* Parameters:
* evt - {Object} The listener argument
*/
removeLayer: function(evt) {
var layer = evt.layer;
if (layer instanceof OpenLayers.Layer.Grid) {
this.clearTileQueue({object: layer});
layer.events.un({
addtile: this.addTile,
retile: this.clearTileQueue,
scope: this
});
}
},
/**
* Method: updateTimeout
* Applies the <moveDelay> or <zoomDelay> to the <drawTilesFromQueue> loop.
*
* Parameters:
* delay - {Number} The delay to apply
*/
updateTimeout: function(delay) {
window.clearTimeout(this.tileQueueId);
if (this.tileQueue.length) {
this.tileQueueId = window.setTimeout(
OpenLayers.Function.bind(this.drawTilesFromQueue, this),
delay
);
}
},
/**
* Method: addTile
* Listener for the layer's addtile event
*
* Parameters:
* evt - {Object} The listener argument
*/
addTile: function(evt) {
evt.tile.events.on({
beforedraw: this.queueTileDraw,
loadstart: this.manageTileCache,
reload: this.manageTileCache,
unload: this.unloadTile,
scope: this
});
},
/**
* Method: unloadTile
* Listener for the tile's unload event
*
* Parameters:
* evt - {Object} The listener argument
*/
unloadTile: function(evt) {
evt.object.events.un({
beforedraw: this.queueTileDraw,
loadstart: this.manageTileCache,
reload: this.manageTileCache,
loadend: this.addToCache,
unload: this.unloadTile,
scope: this
});
OpenLayers.Util.removeItem(this.tileQueue, evt.object);
},
/**
* Method: queueTileDraw
* Adds a tile to the queue that will draw it.
*
* Parameters:
* evt - {Object} Listener argument of the tile's beforedraw event
*/
queueTileDraw: function(evt) {
var tile = evt.object;
var queued = false;
var layer = tile.layer;
// queue only if image with same url not cached already
if (layer.url && (layer.async ||
!this.tileCache[layer.getURL(tile.bounds)])) {
// add to queue only if not in queue already
if (!~OpenLayers.Util.indexOf(this.tileQueue, tile)) {
this.tileQueue.push(tile);
}
queued = true;
}
return !queued;
},
/**
* Method: drawTilesFromQueue
* Draws tiles from the tileQueue, and unqueues the tiles
*/
drawTilesFromQueue: function() {
while (this.tileQueue.length) {
this.tileQueue.shift().draw(true);
}
},
/**
* Method: manageTileCache
* Adds, updates, removes and fetches cache entries.
*
* Parameters:
* evt - {Object} Listener argument of the tile's loadstart event
*/
manageTileCache: function(evt) {
var tile = evt.object;
var img = this.tileCache[tile.url];
// only use images from the cache that are not on a layer already
if (img && (!img.parentNode ||
OpenLayers.Element.hasClass(img.parentNode, 'olBackBuffer'))) {
tile.imgDiv = img;
OpenLayers.Util.removeItem(this.tileCacheIndex, tile.url);
this.tileCacheIndex.push(tile.url);
tile.positionTile();
tile.layer.div.appendChild(tile.imgDiv);
} else if (evt.type === 'loadstart') {
tile.events.register('loadend', this, this.addToCache);
}
},
/**
* Method: addToCache
*
* Parameters:
* evt - {Object} Listener argument for the tile's loadend event
*/
addToCache: function(evt) {
var tile = evt.object;
tile.events.unregister('loadend', this, this.addToCache);
if (!this.tileCache[tile.url]) {
if (!OpenLayers.Element.hasClass(tile.imgDiv, 'olImageLoadError')) {
if (this.tileCacheIndex.length >= this.cacheSize) {
delete this.tileCache[this.tileCacheIndex[0]];
this.tileCacheIndex.shift();
}
this.tileCache[tile.url] = tile.imgDiv;
this.tileCacheIndex.push(tile.url);
}
}
},
/**
* Method: clearTileQueue
* Clears the tile queue from tiles of a specific layer
*
* Parameters:
* evt - {Object} Listener argument of the layer's retile event
*/
clearTileQueue: function(evt) {
var layer = evt.object;
for (var i=this.tileQueue.length-1; i>=0; --i) {
if (this.tileQueue[i].layer === layer) {
this.tileQueue.splice(i, 1);
}
}
}
});
/**
* APIProperty: OpenLayers.TileManager.cacheSize
* {Number} Number of image elements to keep referenced in the shared cache
* for fast reuse. Default is 512.
*/
OpenLayers.TileManager.cacheSize = 512;