Skip to content

Commit

Permalink
Merge pull request openlayers#16 from elemoine/bigbackbuffer
Browse files Browse the repository at this point in the history
A Big Back Buffer approach
  • Loading branch information
Éric Lemoine committed Nov 2, 2011
2 parents bea1a5b + c65471c commit 0bf1169
Show file tree
Hide file tree
Showing 11 changed files with 614 additions and 560 deletions.
1 change: 0 additions & 1 deletion lib/OpenLayers.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@
"OpenLayers/Marker/Box.js",
"OpenLayers/Popup.js",
"OpenLayers/Tile.js",
"OpenLayers/Tile/BackBufferable.js",
"OpenLayers/Tile/Image.js",
"OpenLayers/Tile/Image/IFrame.js",
"OpenLayers/Tile/WFS.js",
Expand Down
7 changes: 0 additions & 7 deletions lib/OpenLayers/Layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -314,13 +314,6 @@ OpenLayers.Layer = OpenLayers.Class({
*/
transitionEffect: null,

/**
* Property: SUPPORTED_TRANSITIONS
* {Array} An immutable (that means don't change it!) list of supported
* transitionEffect values.
*/
SUPPORTED_TRANSITIONS: ['resize'],

/**
* Property: metadata
* {Object} This object can be used to store additional information on a
Expand Down
173 changes: 162 additions & 11 deletions lib/OpenLayers/Layer/Grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,34 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
*/
timerId: null,

/**
* Property: backBuffer
* {DOMElement} The back buffer.
*/
backBuffer: null,

/**
* Property: gridResolution
* {Number} The resolution of the current grid. Used for backbuffering.
* This property is updated each the grid is initialized.
*/
gridResolution: null,

/**
* Property: backBufferResolution
* {Number} The resolution of the current back buffer. This property is
* updated each time a back buffer is created.
*/
backBufferResolution: null,

/**
* Property: backBufferLonLat
* {Object} The top-left corner of the current back buffer. Includes lon
* and lat properties. This object is updated each time a back buffer
* is created.
*/
backBufferLonLat: null,

/**
* Constructor: OpenLayers.Layer.Grid
* Create a new grid layer
Expand All @@ -133,7 +161,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
this.events.addEventType("tileloaded");

this.grid = [];

this._moveGriddedTiles = OpenLayers.Function.bind(
this.moveGriddedTiles, this
);
Expand All @@ -159,6 +187,9 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
*/
destroy: function() {
this.clearGrid();
// clearGrid should remove any back buffer from the layer,
// so no need to call removeBackBuffer here

this.grid = null;
this.tileSize = null;
OpenLayers.Layer.HTTPRequest.prototype.destroy.apply(this, arguments);
Expand All @@ -180,6 +211,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
}
}
this.grid = [];
this.gridResolution = null;
}
},

Expand Down Expand Up @@ -212,6 +244,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {

// we do not want to copy reference to grid, so we make a new array
obj.grid = [];
obj.gridResolution = null;

return obj;
},
Expand Down Expand Up @@ -240,14 +273,37 @@ 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
// current bounds is not contained by our tile.
// (thus, we do not specify partial -- its default is false)

if ( forceReTile ||
(!dragging && !tilesBounds.containsBounds(bounds))) {

// In single tile mode with no transition effect, we insert
// a non-scaled backbuffer when the layer is moved. But if
// a zoom occurs right after a move, i.e. before the new
// image is received, we need to remove the backbuffer, or
// an ill-positioned image will be visible during the zoom
// transition.

if(zoomChanged && this.transitionEffect !== 'resize') {
this.removeBackBuffer();
}

if(!zoomChanged || this.transitionEffect === 'resize') {
this.applyBackBuffer(serverResolution);
}

this.initSingleTile(bounds);
}
} else {
Expand All @@ -260,10 +316,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) {
Expand All @@ -281,6 +333,9 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
}

if(forceReTile) {
if(zoomChanged && this.transitionEffect === 'resize') {
this.applyBackBuffer(serverResolution);
}
this.initGriddedTiles(bounds);
} else {
this.scheduleMoveGriddedTiles();
Expand All @@ -306,7 +361,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
if(this.serverResolutions &&
OpenLayers.Util.indexOf(this.serverResolutions, resolution) === -1) {
var i, serverResolution;
for(var i=this.serverResolutions.length-1; i>= 0; i--) {
for(i=this.serverResolutions.length-1; i>= 0; i--) {
serverResolution = this.serverResolutions[i];
if(serverResolution > resolution) {
resolution = serverResolution;
Expand Down Expand Up @@ -352,14 +407,13 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
var size = this.map.getSize();
var lcX = parseInt(this.map.layerContainerDiv.style.left, 10);
var lcY = parseInt(this.map.layerContainerDiv.style.top, 10);
var x = (lcX - (size.w / 2.)) * (scale - 1);
var y = (lcY - (size.h / 2.)) * (scale - 1);
var x = (lcX - (size.w / 2.0)) * (scale - 1);
var y = (lcY - (size.h / 2.0)) * (scale - 1);

this.div.style.left = x + '%';
this.div.style.top = y + '%';
},


/**
* Method: getResolutionScale
* Return the value by which the layer is currently scaled.
Expand All @@ -371,6 +425,96 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
return parseInt(this.div.style.width, 10) / 100;
},

/**
* Method: applyBackBuffer
* Create, insert, scale and position a back buffer for the layer.
*
* Parameters:
* resolution - {Number} The resolution to transition to.
*/
applyBackBuffer: function(resolution) {
var backBuffer = this.backBuffer;
if(!backBuffer) {
backBuffer = this.createBackBuffer();
if(!backBuffer) {
return;
}
this.div.insertBefore(backBuffer, this.div.firstChild);
this.backBuffer = backBuffer;

// set some information in the instance for subsequent
// calls to applyBackBuffer where the same back buffer
// is reused
var topLeftTileBounds = this.grid[0][0].bounds;
this.backBufferLonLat = {
lon: topLeftTileBounds.left,
lat: topLeftTileBounds.top
};
this.backBufferResolution = this.gridResolution;
}

var style = backBuffer.style;

// scale the back buffer
var ratio = this.backBufferResolution / resolution;
style.width = 100 * ratio + '%';
style.height = 100 * ratio + '%';

// and position it (based on the grid's top-left corner)
var position = this.getViewPortPxFromLonLat(
this.backBufferLonLat, 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.
*
* Returns:
* {DOMElement} The DOM element for the back buffer, undefined if the
* grid isn't initialized yet.
*/
createBackBuffer: function() {
var backBuffer;
if(this.grid.length > 0) {
backBuffer = document.createElement('div');
backBuffer.id = this.div.id + '_bb';
backBuffer.className = 'olBackBuffer';
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].createBackBuffer();
if(!tile) {
continue;
}
// to be able to correctly position the back buffer we
// place the tiles grid at (0, 0) in the back buffer
tile.style.top = (i * this.tileSize.h) + '%';
tile.style.left = (j * this.tileSize.w) + '%';
backBuffer.appendChild(tile);
}
}
}
return backBuffer;
},

/**
* Method: removeBackBuffer
* Remove back buffer from DOM.
*/
removeBackBuffer: function() {
if(this.backBuffer && this.backBuffer.parentNode) {
this.div.removeChild(this.backBuffer);
this.backBuffer = null;
this.backBufferResolution = null;
}
},

/**
* Method: moveByPx
* Move the layer based on pixel vector.
Expand Down Expand Up @@ -500,6 +644,9 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {

//remove all but our single tile
this.removeExcessTiles(1,1);

// store the resolution of the grid
this.gridResolution = this.getServerResolution();
},

/**
Expand Down Expand Up @@ -660,6 +807,9 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
//shave off exceess rows and colums
this.removeExcessTiles(rowidx, colidx);

// store the resolution of the grid
this.gridResolution = this.getServerResolution();

//now actually draw the tiles
this.spiralTileLoad();
},
Expand Down Expand Up @@ -790,6 +940,7 @@ 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");
this.removeBackBuffer();
}
};
tile.events.register("loadend", this, tile.onLoadEnd);
Expand Down Expand Up @@ -993,6 +1144,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
tileLeft + tileMapWidth,
tileBottom + tileMapHeight);
},

CLASS_NAME: "OpenLayers.Layer.Grid"
});
Loading

0 comments on commit 0bf1169

Please sign in to comment.