No more percentage based positioning.
Client zoom now supports both over- and undersampling.
This commit is contained in:
+90
-115
@@ -168,8 +168,9 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
|
||||
/**
|
||||
* Property: gridResolution
|
||||
* {Number} The resolution of the current grid. Used for backbuffering.
|
||||
* This property is updated each the grid is initialized.
|
||||
* {Number} The resolution of the current grid. Used for backbuffer and
|
||||
* client zoom. This property is updated every time the grid is
|
||||
* initialized.
|
||||
*/
|
||||
gridResolution: null,
|
||||
|
||||
@@ -458,7 +459,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
}
|
||||
|
||||
if(!zoomChanged || this.transitionEffect === 'resize') {
|
||||
this.applyBackBuffer(serverResolution);
|
||||
this.applyBackBuffer(resolution);
|
||||
}
|
||||
|
||||
this.initSingleTile(bounds);
|
||||
@@ -477,25 +478,9 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
this.map.getMaxExtent()
|
||||
});
|
||||
|
||||
if(resolution !== serverResolution) {
|
||||
bounds = this.map.calculateBounds(null, serverResolution);
|
||||
if(forceReTile) {
|
||||
// stretch the layer div
|
||||
var scale = serverResolution / resolution;
|
||||
this.transformDiv(scale);
|
||||
}
|
||||
} else {
|
||||
// reset the layer width, height, left, top, to deal with
|
||||
// the case where the layer was previously transformed
|
||||
this.div.style.width = '100%';
|
||||
this.div.style.height = '100%';
|
||||
this.div.style.left = '0%';
|
||||
this.div.style.top = '0%';
|
||||
}
|
||||
|
||||
if(forceReTile) {
|
||||
if(zoomChanged && this.transitionEffect === 'resize') {
|
||||
this.applyBackBuffer(serverResolution);
|
||||
this.applyBackBuffer(resolution);
|
||||
}
|
||||
this.initGriddedTiles(bounds);
|
||||
} else {
|
||||
@@ -620,7 +605,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
|
||||
/**
|
||||
* Method: getServerResolution
|
||||
* Return the closest highest server-supported resolution. Throw an
|
||||
* Return the closest server-supported resolution. Throw an
|
||||
* exception if none is found in the serverResolutions array.
|
||||
*
|
||||
* Parameters:
|
||||
@@ -628,23 +613,24 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
* map resolution is used.
|
||||
*
|
||||
* Returns:
|
||||
* {Number} The closest highest server resolution value.
|
||||
* {Number} The closest server resolution value.
|
||||
*/
|
||||
getServerResolution: function(resolution) {
|
||||
var distance = Number.POSITIVE_INFINITY;
|
||||
resolution = resolution || this.map.getResolution();
|
||||
if(this.serverResolutions &&
|
||||
OpenLayers.Util.indexOf(this.serverResolutions, resolution) === -1) {
|
||||
var i, serverResolution;
|
||||
var i, newDistance, newResolution, serverResolution;
|
||||
for(i=this.serverResolutions.length-1; i>= 0; i--) {
|
||||
serverResolution = this.serverResolutions[i];
|
||||
if(serverResolution > resolution) {
|
||||
resolution = serverResolution;
|
||||
newResolution = this.serverResolutions[i];
|
||||
newDistance = Math.abs(newResolution - resolution);
|
||||
if (newDistance > distance) {
|
||||
break;
|
||||
}
|
||||
distance = newDistance;
|
||||
serverResolution = newResolution;
|
||||
}
|
||||
if(i === -1) {
|
||||
throw 'no appropriate resolution in serverResolutions';
|
||||
}
|
||||
resolution = serverResolution;
|
||||
}
|
||||
return resolution;
|
||||
},
|
||||
@@ -665,33 +651,6 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
this.map.getZoomForResolution(resolution) + (this.zoomOffset || 0);
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: transformDiv
|
||||
* Transform the layer div.
|
||||
*
|
||||
* Parameters:
|
||||
* scale - {Number} The value by which the layer div is to
|
||||
* be scaled.
|
||||
*/
|
||||
transformDiv: function(scale) {
|
||||
|
||||
// scale the layer div
|
||||
|
||||
this.div.style.width = 100 * scale + '%';
|
||||
this.div.style.height = 100 * scale + '%';
|
||||
|
||||
// and translate the layer div as necessary
|
||||
|
||||
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.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.
|
||||
@@ -733,21 +692,26 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
};
|
||||
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 + '%';
|
||||
|
||||
// scale the tiles inside the back buffer
|
||||
var tiles = backBuffer.childNodes, tile;
|
||||
for (var i=tiles.length-1; i>=0; --i) {
|
||||
tile = tiles[i];
|
||||
tile.style.top = ((ratio * tile._i * tile._h) | 0) + 'px';
|
||||
tile.style.left = ((ratio * tile._j * tile._w) | 0) + 'px';
|
||||
tile.style.width = Math.round(ratio * tile._w) + 'px';
|
||||
tile.style.height = Math.round(ratio * tile._h) + 'px';
|
||||
}
|
||||
|
||||
// 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 = Math.round(position.x - leftOffset) + '%';
|
||||
backBuffer.style.top = Math.round(position.y - topOffset) + '%';
|
||||
var leftOffset = this.map.layerContainerOriginPx.x;
|
||||
var topOffset = this.map.layerContainerOriginPx.y;
|
||||
backBuffer.style.left = Math.round(position.x - leftOffset) + 'px';
|
||||
backBuffer.style.top = Math.round(position.y - topOffset) + 'px';
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -765,19 +729,17 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
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;
|
||||
var tile = this.grid[i][j],
|
||||
markup = this.grid[i][j].createBackBuffer();
|
||||
if (markup) {
|
||||
markup._i = i;
|
||||
markup._j = j;
|
||||
markup._w = tile.size.w;
|
||||
markup._h = tile.size.h;
|
||||
backBuffer.appendChild(markup);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -923,16 +885,22 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
var tilelon = resolution * this.tileSize.w;
|
||||
var tilelat = resolution * this.tileSize.h;
|
||||
|
||||
var ratio = resolution / this.map.getResolution(),
|
||||
tileSize = {
|
||||
w: Math.round(this.tileSize.w * ratio),
|
||||
h: Math.round(this.tileSize.h * ratio)
|
||||
};
|
||||
|
||||
var offsetlon = bounds.left - origin.lon;
|
||||
var tilecol = Math.floor(offsetlon/tilelon) - this.buffer;
|
||||
var tilecolremain = offsetlon/tilelon - tilecol;
|
||||
var tileoffsetx = -tilecolremain * this.tileSize.w;
|
||||
var tileoffsetx = -tilecolremain * tileSize.w;
|
||||
var tileoffsetlon = origin.lon + tilecol * tilelon;
|
||||
|
||||
var offsetlat = bounds.top - (origin.lat + tilelat);
|
||||
var tilerow = Math.ceil(offsetlat/tilelat) + this.buffer;
|
||||
var tilerowremain = tilerow - offsetlat/tilelat;
|
||||
var tileoffsety = -tilerowremain * this.tileSize.h;
|
||||
var tileoffsety = -tilerowremain * tileSize.h;
|
||||
var tileoffsetlat = origin.lat + tilerow * tilelat;
|
||||
|
||||
return {
|
||||
@@ -982,19 +950,25 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
// tiles required to cover the viewport plus at least one for panning
|
||||
|
||||
var viewSize = this.map.getSize();
|
||||
var minRows = Math.ceil(viewSize.h/this.tileSize.h) +
|
||||
2 * this.buffer + 1;
|
||||
var minCols = Math.ceil(viewSize.w/this.tileSize.w) +
|
||||
2 * this.buffer + 1;
|
||||
|
||||
var origin = this.getTileOrigin();
|
||||
var resolution = this.getServerResolution();
|
||||
|
||||
var tileLayout = this.calculateGridLayout(bounds, origin, resolution);
|
||||
var resolution = this.map.getResolution(),
|
||||
serverResolution = this.getServerResolution(),
|
||||
ratio = resolution / serverResolution,
|
||||
tileSize = {
|
||||
w: this.tileSize.w / ratio,
|
||||
h: this.tileSize.h / ratio
|
||||
};
|
||||
|
||||
var minRows = Math.ceil(viewSize.h/tileSize.h) +
|
||||
2 * this.buffer + 1;
|
||||
var minCols = Math.ceil(viewSize.w/tileSize.w) +
|
||||
2 * this.buffer + 1;
|
||||
|
||||
var tileLayout = this.calculateGridLayout(bounds, origin, serverResolution);
|
||||
var tileoffsetx = Math.round(tileLayout.tileoffsetx); // heaven help us
|
||||
var tileoffsety = Math.round(tileLayout.tileoffsety);
|
||||
|
||||
|
||||
var tileoffsetlon = tileLayout.tileoffsetlon;
|
||||
var tileoffsetlat = tileLayout.tileoffsetlat;
|
||||
|
||||
@@ -1006,8 +980,8 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
|
||||
var rowidx = 0;
|
||||
|
||||
var layerContainerDivLeft = parseInt(this.map.layerContainerDiv.style.left);
|
||||
var layerContainerDivTop = parseInt(this.map.layerContainerDiv.style.top);
|
||||
var layerContainerDivLeft = this.map.layerContainerOriginPx.x;
|
||||
var layerContainerDivTop = this.map.layerContainerOriginPx.y;
|
||||
|
||||
var tileData = [], center = this.map.getCenter();
|
||||
do {
|
||||
@@ -1051,27 +1025,29 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
});
|
||||
|
||||
tileoffsetlon += tilelon;
|
||||
tileoffsetx += this.tileSize.w;
|
||||
tileoffsetx += tileSize.w;
|
||||
} while ((tileoffsetlon <= bounds.right + tilelon * this.buffer)
|
||||
|| colidx < minCols);
|
||||
|
||||
tileoffsetlat -= tilelat;
|
||||
tileoffsety += this.tileSize.h;
|
||||
tileoffsety += tileSize.h;
|
||||
} while((tileoffsetlat >= bounds.bottom - tilelat * this.buffer)
|
||||
|| rowidx < minRows);
|
||||
|
||||
//shave off exceess rows and colums
|
||||
this.removeExcessTiles(rowidx, colidx);
|
||||
|
||||
var resolution = this.getServerResolution(),
|
||||
immediately = resolution === this.gridResolution;
|
||||
// store the resolution of the grid
|
||||
this.gridResolution = this.getServerResolution();
|
||||
this.gridResolution = resolution;
|
||||
|
||||
//now actually draw the tiles
|
||||
tileData.sort(function(a, b) {
|
||||
return a.distance - b.distance;
|
||||
});
|
||||
for (var i=0, ii=tileData.length; i<ii; ++i) {
|
||||
tileData[i].tile.draw();
|
||||
tileData[i].tile.draw(immediately);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1194,28 +1170,27 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
return;
|
||||
}
|
||||
var buffer = this.buffer + 1;
|
||||
var scale = this.getResolutionScale();
|
||||
while(true) {
|
||||
var tlTile = this.grid[0][0];
|
||||
var tlViewPort = {
|
||||
x: (this.grid[0][0].position.x * scale) +
|
||||
parseInt(this.div.style.left, 10) +
|
||||
parseInt(this.map.layerContainerDiv.style.left),
|
||||
y: (this.grid[0][0].position.y * scale) +
|
||||
parseInt(this.div.style.top, 10) +
|
||||
parseInt(this.map.layerContainerDiv.style.top)
|
||||
x: tlTile.position.x +
|
||||
this.map.layerContainerOriginPx.x,
|
||||
y: tlTile.position.y +
|
||||
this.map.layerContainerOriginPx.y
|
||||
};
|
||||
var ratio = this.getServerResolution() / this.map.getResolution();
|
||||
var tileSize = {
|
||||
w: this.tileSize.w * scale,
|
||||
h: this.tileSize.h * scale
|
||||
w: Math.round(this.tileSize.w * ratio),
|
||||
h: Math.round(this.tileSize.h * ratio)
|
||||
};
|
||||
if (tlViewPort.x > -tileSize.w * (buffer - 1)) {
|
||||
this.shiftColumn(true);
|
||||
this.shiftColumn(true, tileSize);
|
||||
} else if (tlViewPort.x < -tileSize.w * buffer) {
|
||||
this.shiftColumn(false);
|
||||
this.shiftColumn(false, tileSize);
|
||||
} else if (tlViewPort.y > -tileSize.h * (buffer - 1)) {
|
||||
this.shiftRow(true);
|
||||
this.shiftRow(true, tileSize);
|
||||
} else if (tlViewPort.y < -tileSize.h * buffer) {
|
||||
this.shiftRow(false);
|
||||
this.shiftRow(false, tileSize);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@@ -1229,15 +1204,15 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
* Parameters:
|
||||
* prepend - {Boolean} if true, prepend to beginning.
|
||||
* if false, then append to end
|
||||
* tileSize - {<OpenLayers.Size>} rendered tile size
|
||||
*/
|
||||
shiftRow:function(prepend) {
|
||||
shiftRow:function(prepend, tileSize) {
|
||||
var modelRowIndex = (prepend) ? 0 : (this.grid.length - 1);
|
||||
var grid = this.grid;
|
||||
var modelRow = grid[modelRowIndex];
|
||||
|
||||
var resolution = this.getServerResolution();
|
||||
var deltaY = (prepend) ? -this.tileSize.h : this.tileSize.h;
|
||||
var deltaLat = resolution * -deltaY;
|
||||
var sign = prepend ? -1 : 1;
|
||||
var deltaLat = this.getServerResolution() * -sign * this.tileSize.h;
|
||||
|
||||
var row = (prepend) ? grid.pop() : grid.shift();
|
||||
|
||||
@@ -1247,7 +1222,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
var position = modelTile.position.clone();
|
||||
bounds.bottom = bounds.bottom + deltaLat;
|
||||
bounds.top = bounds.top + deltaLat;
|
||||
position.y = position.y + deltaY;
|
||||
position.y = position.y + sign * tileSize.h;
|
||||
row[i].moveTo(bounds, position);
|
||||
}
|
||||
|
||||
@@ -1265,11 +1240,11 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
* Parameters:
|
||||
* prepend - {Boolean} if true, prepend to beginning.
|
||||
* if false, then append to end
|
||||
* tileSize - {<OpenLayers.Size>} rendered tile size
|
||||
*/
|
||||
shiftColumn: function(prepend) {
|
||||
var deltaX = (prepend) ? -this.tileSize.w : this.tileSize.w;
|
||||
var resolution = this.getServerResolution();
|
||||
var deltaLon = resolution * deltaX;
|
||||
shiftColumn: function(prepend, tileSize) {
|
||||
var sign = prepend ? -1 : 1;
|
||||
var deltaLon = this.getServerResolution() * sign * this.tileSize.w;
|
||||
|
||||
for (var i=0, len=this.grid.length; i<len; i++) {
|
||||
var row = this.grid[i];
|
||||
@@ -1280,7 +1255,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
var position = modelTile.position.clone();
|
||||
bounds.left = bounds.left + deltaLon;
|
||||
bounds.right = bounds.right + deltaLon;
|
||||
position.x = position.x + deltaX;
|
||||
position.x = position.x + sign * tileSize.w;
|
||||
|
||||
var tile = prepend ? this.grid[i].pop() : this.grid[i].shift();
|
||||
tile.moveTo(bounds, position);
|
||||
|
||||
@@ -482,9 +482,9 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
|
||||
viewHeight = viewSize.h,
|
||||
offsetLeft = (viewWidth / 2 * this.ratio) - viewWidth / 2,
|
||||
offsetTop = (viewHeight / 2 * this.ratio) - viewHeight / 2;
|
||||
offsetLeft += parseInt(this.map.layerContainerDiv.style.left, 10);
|
||||
offsetLeft += this.map.layerContainerOriginPx.x;
|
||||
offsetLeft = -Math.round(offsetLeft);
|
||||
offsetTop += parseInt(this.map.layerContainerDiv.style.top, 10);
|
||||
offsetTop += this.map.layerContainerOriginPx.y;
|
||||
offsetTop = -Math.round(offsetTop);
|
||||
|
||||
this.div.style.left = offsetLeft + 'px';
|
||||
|
||||
Reference in New Issue
Block a user