better back buffer code, and support for singleTile

This commit is contained in:
Éric Lemoine
2011-10-16 22:31:37 +02:00
parent 8ca9f22cf5
commit bea037679f

View File

@@ -111,7 +111,17 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
*/
timerId: null,
backBufferData: null,
/**
* Property: backBuffer
* {DOMElement} The back buffer.
*/
backBuffer: null,
/**
* Property: lastResolution
* {Object} The last resolution of the grid.
*/
lastResolution: null,
/**
* Constructor: OpenLayers.Layer.Grid
@@ -135,8 +145,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
this.events.addEventType("tileloaded");
this.grid = [];
this.backBufferData = {};
this._moveGriddedTiles = OpenLayers.Function.bind(
this.moveGriddedTiles, this
);
@@ -219,10 +228,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
return obj;
},
setBackBufferData: function() {
this.backBufferData.resolution = this.getServerResolution();
},
/**
* Method: moveTo
* This function is called whenever the map is moved. All the moving
@@ -247,7 +252,13 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
// total bounds of the tiles
var tilesBounds = this.getTilesBounds();
// the new map resolution
var resolution = this.map.getResolution();
// the server-supported resolution for the new map resolution
var serverResolution = this.getServerResolution(resolution);
if (this.singleTile) {
// We want to redraw whenever even the slightest part of the
@@ -255,6 +266,11 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
// (thus, we do not specify partial -- its default is false)
if ( forceReTile ||
(!dragging && !tilesBounds.containsBounds(bounds))) {
if(this.lastResolution === serverResolution ||
(this.lastResolution &&
this.transitionEffect === 'resize')) {
this.insertBackBuffer(serverResolution, tilesBounds);
}
this.initSingleTile(bounds);
}
} else {
@@ -267,10 +283,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
forceReTile = forceReTile ||
!tilesBounds.containsBounds(bounds, true);
var resolution = this.map.getResolution();
var serverResolution =
this.getServerResolution(resolution);
if(resolution !== serverResolution) {
bounds = this.map.calculateBounds(null, serverResolution);
if(forceReTile) {
@@ -288,30 +300,11 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
}
if(forceReTile) {
if(OpenLayers.Util.indexOf(
this.SUPPORTED_TRANSITIONS,
this.transitionEffect) != -1) {
if(!this.backBufferData.backBuffer) {
this.backBufferData.backBuffer = this.createBackBuffer();
if(this.backBufferData.backBuffer) {
this.div.insertBefore(this.backBufferData.backBuffer,
this.div.firstChild);
}
}
if(this.backBufferData.backBuffer && this.backBufferData.resolution) {
var resolution = this.getServerResolution();
var scale = this.backBufferData.resolution / resolution;
this.backBufferData.backBuffer.style.width = 100 * scale + '%';
this.backBufferData.backBuffer.style.height = 100 * scale + '%';
var lonLat = {lon: tilesBounds.left, lat: tilesBounds.top},
position = this.getViewPortPxFromLonLat(lonLat, resolution);
this.backBufferData.backBuffer.style.left = position.x + '%';
this.backBufferData.backBuffer.style.top = position.y + '%';
}
if(this.transitionEffect === 'resize' &&
(this.lastResolution &&
(this.lastResolution !== serverResolution))) {
this.insertBackBuffer(serverResolution, tilesBounds);
}
this.initGriddedTiles(bounds);
} else {
this.scheduleMoveGriddedTiles();
@@ -320,31 +313,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
}
},
createBackBuffer: function() {
var backBuffer;
if(this.grid.length > 0) {
var backBuffer = document.createElement('div');
backBuffer.id = this.div.id + '_bb';
backBuffer.style.position = 'absolute';
backBuffer.style.left = '0%';
backBuffer.style.top = '0%';
backBuffer.style.width = '100%';
backBuffer.style.height = '100%';
for(var i=0, lenI=this.grid.length; i<lenI; i++) {
for(var j=0, lenJ=this.grid[i].length; j<lenJ; j++) {
var tile = this.grid[i][j].cloneMarkup();
if(!tile) {
return;
}
tile.style.left = (j * this.tileSize.w) + '%';
tile.style.top = (i * this.tileSize.h) + '%';
backBuffer.appendChild(tile);
}
}
}
return backBuffer;
},
/**
* Method: getServerResolution
* Return the server-supported resolution that is the closest to
@@ -415,7 +383,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
this.div.style.top = y + '%';
},
/**
* Method: getResolutionScale
* Return the value by which the layer is currently scaled.
@@ -427,6 +394,75 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
return parseInt(this.div.style.width, 10) / 100;
},
/**
* Method: insertBackBuffer
* Insert a back buffer for a better transition.
*
* Parameters:
* resolution - {Number} The resolution to transition to.
* tilesBounds - {<OpenLayers.Bounds>} The current bounds of the tiles.
*/
insertBackBuffer: function(resolution, tilesBounds) {
var backBuffer = this.backBuffer;
if(!backBuffer) {
backBuffer = this.createBackBuffer();
if(!backBuffer) {
return;
}
this.div.insertBefore(backBuffer, this.div.firstChild);
this.backBuffer = backBuffer;
}
var style = backBuffer.style;
// scale
var ratio = this.lastResolution / resolution;
style.width = 100 * ratio + '%';
style.height = 100 * ratio + '%';
// and position
var position = this.getViewPortPxFromLonLat(
{lon: tilesBounds.left, lat: tilesBounds.top}, resolution);
var leftOffset = parseInt(this.map.layerContainerDiv.style.left, 10);
var topOffset = parseInt(this.map.layerContainerDiv.style.top, 10);
backBuffer.style.left = (position.x - leftOffset) + '%';
backBuffer.style.top = (position.y - topOffset) + '%';
},
/**
* Method: createBackBuffer
* Create a back buffer. We apply a best effort strategy here - if for any
* reason we cannot clone a tile's markup we give up right away.
*
* Returns:
* {DOMElement} The DOM element for the back buffer, undefined if the
* back buffer couldn't have been created.
*/
createBackBuffer: function() {
var backBuffer;
if(this.grid.length > 0) {
var backBuffer = document.createElement('div');
backBuffer.id = this.div.id + '_bb';
backBuffer.style.position = 'absolute';
backBuffer.style.width = '100%';
backBuffer.style.height = '100%';
for(var i=0, lenI=this.grid.length; i<lenI; i++) {
for(var j=0, lenJ=this.grid[i].length; j<lenJ; j++) {
var tile = this.grid[i][j].cloneMarkup();
if(!tile) {
return;
}
// to be able to correctly position the back buffer we
// place the first tile at (0, 0) in the back buffer
tile.style.left = (j * this.tileSize.w) + '%';
tile.style.top = (i * this.tileSize.h) + '%';
backBuffer.appendChild(tile);
}
}
}
return backBuffer;
},
/**
* Method: moveByPx
* Move the layer based on pixel vector.
@@ -846,11 +882,11 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
//if that was the last tile, then trigger a 'loadend' on the layer
if (this.numLoadingTiles == 0) {
this.events.triggerEvent("loadend");
if(this.backBufferData.backBuffer) {
this.div.removeChild(this.backBufferData.backBuffer);
this.backBufferData.backBuffer = null;
if(this.backBuffer && this.backBuffer.parentNode) {
this.div.removeChild(this.backBuffer);
this.backBuffer = null;
}
this.setBackBufferData();
this.lastResolution = this.getServerResolution();
}
};
tile.events.register("loadend", this, tile.onLoadEnd);