+
+ This example demonstrates the "client zoom"
+ functionality, where OpenLayers stretches the layer div when the
+ resolution is not supported by that layer's tile service.
+
+
+
+
+
+
+
+
+
+ The map of this example is configured with 22 resolutions, while
+ the OSM tile server supports the first 19 resolutions only. When
+ the zoom level is 19, 20 or 21 "client zoom" is applied to the OSM
+ layer, i.e. the OSM layer div is stretched as necessary. The map's
+ initial zoom is 18. So if you zoom in using the zoom bar's "+"
+ button you'll effectively trigger "client zoom".
+
+
+
+
+
+ For demonstration purpose the map of this example has
+ fractionalZoom set to true. So "client zoom" also
+ applies if you choose arbitrary zoom levels using the slider of the
+ zoom bar, or shift-drag boxes to zoom to arbitrary extents.
+ "client zoom" therefore allows continous zooming for tiled layers.
+
+
+
+
+
+ Enabling "client zoom" on a layer is done by passing
+ serverResolutions to the layer constructor.
+ serverResolutions is the list of resolutions supported
+ by the tile service. See the clientzoom.js source.
+
+
+
+
+
diff --git a/examples/clientzoom.js b/examples/clientzoom.js
new file mode 100644
index 0000000000..65ae758c3c
--- /dev/null
+++ b/examples/clientzoom.js
@@ -0,0 +1,43 @@
+var map;
+
+function init() {
+
+ map = new OpenLayers.Map({
+ div: "map",
+ projection: "EPSG:900913",
+ units: "m",
+ maxExtent: new OpenLayers.Bounds(
+ -20037508.34, -20037508.34, 20037508.34, 20037508.34
+ ),
+ controls: [],
+ fractionalZoom: true
+ });
+
+ var osm = new OpenLayers.Layer.OSM(null, null, {
+ resolutions: [156543.03390625, 78271.516953125, 39135.7584765625,
+ 19567.87923828125, 9783.939619140625, 4891.9698095703125,
+ 2445.9849047851562, 1222.9924523925781, 611.4962261962891,
+ 305.74811309814453, 152.87405654907226, 76.43702827453613,
+ 38.218514137268066, 19.109257068634033, 9.554628534317017,
+ 4.777314267158508, 2.388657133579254, 1.194328566789627,
+ 0.5971642833948135, 0.25, 0.1, 0.05],
+ serverResolutions: [156543.03390625, 78271.516953125, 39135.7584765625,
+ 19567.87923828125, 9783.939619140625,
+ 4891.9698095703125, 2445.9849047851562,
+ 1222.9924523925781, 611.4962261962891,
+ 305.74811309814453, 152.87405654907226,
+ 76.43702827453613, 38.218514137268066,
+ 19.109257068634033, 9.554628534317017,
+ 4.777314267158508, 2.388657133579254,
+ 1.194328566789627, 0.5971642833948135],
+ transitionEffect: 'resize'
+ });
+
+ map.addLayers([osm]);
+ map.addControls([
+ new OpenLayers.Control.Navigation(),
+ new OpenLayers.Control.Attribution(),
+ new OpenLayers.Control.PanZoomBar()
+ ]);
+ map.setCenter(new OpenLayers.LonLat(659688.852138, 5710701.2962197), 18);
+}
diff --git a/lib/OpenLayers/Layer.js b/lib/OpenLayers/Layer.js
index 4a6bd4c80d..46ec873be7 100644
--- a/lib/OpenLayers/Layer.js
+++ b/lib/OpenLayers/Layer.js
@@ -1245,11 +1245,11 @@ OpenLayers.Layer = OpenLayers.Class({
* {} An which is the passed-in
* ,translated into view port pixels.
*/
- getViewPortPxFromLonLat: function (lonlat) {
+ getViewPortPxFromLonLat: function (lonlat, resolution) {
var px = null;
if (lonlat != null) {
- var resolution = this.map.getResolution();
- var extent = this.map.getExtent();
+ resolution = resolution || this.map.getResolution();
+ var extent = this.map.calculateBounds(null, resolution);
px = new OpenLayers.Pixel(
(1/resolution * (lonlat.lon - extent.left)),
(1/resolution * (extent.top - lonlat.lat))
diff --git a/lib/OpenLayers/Layer/Grid.js b/lib/OpenLayers/Layer/Grid.js
index 696d6e92cf..e5fa551c9f 100644
--- a/lib/OpenLayers/Layer/Grid.js
+++ b/lib/OpenLayers/Layer/Grid.js
@@ -98,6 +98,13 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
*/
tileLoadingDelay: 100,
+ /**
+ * Property: serverResolutions
+ * {Array(Number}} This property is documented in subclasses as
+ * an API property.
+ */
+ serverResolutions: null,
+
/**
* Property: timerId
* {Number} - The id of the tileLoadingDelay timer.
@@ -221,8 +228,9 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
* dragging - {Boolean}
*/
moveTo:function(bounds, zoomChanged, dragging) {
+
OpenLayers.Layer.HTTPRequest.prototype.moveTo.apply(this, arguments);
-
+
bounds = bounds || this.map.getExtent();
if (bounds != null) {
@@ -238,18 +246,41 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
// 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 ||
+ if ( forceReTile ||
(!dragging && !tilesBounds.containsBounds(bounds))) {
this.initSingleTile(bounds);
}
} else {
-
+
// if the bounds have changed such that they are not even
// *partially* contained by our tiles (IE user has
// programmatically panned to the other side of the earth)
// then we want to reTile (thus, partial true).
- //
- if (forceReTile || !tilesBounds.containsBounds(bounds, true)) {
+
+ 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) {
+ // 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) {
this.initGriddedTiles(bounds);
} else {
this.scheduleMoveGriddedTiles();
@@ -258,6 +289,88 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
}
},
+ /**
+ * Method: getServerResolution
+ * Return the server-supported resolution that is the closest to
+ * the resolution passed as a parameter. If no resolution is
+ * passed the map resolution is used.
+ *
+ * Parameters:
+ * resolution - {Number} The base resolution.
+ *
+ * Returns:
+ * {Number} The closest server supported resolution.
+ */
+ getServerResolution: function(resolution) {
+ resolution = resolution || this.map.getResolution();
+ if(this.serverResolutions &&
+ OpenLayers.Util.indexOf(this.serverResolutions, resolution) === -1) {
+ var i, serverResolution;
+ for(var i=this.serverResolutions.length-1; i>= 0; i--) {
+ serverResolution = this.serverResolutions[i];
+ if(serverResolution > resolution) {
+ resolution = serverResolution;
+ break;
+ }
+ }
+ if(i === -1) {
+ throw 'no appropriate resolution in serverResolutions';
+ }
+ }
+ return resolution;
+ },
+
+ /**
+ * Method: getServerZoom
+ * Return the zoom value corresponding to the best zoom supported by the server
+ * resolution.
+ *
+ * Returns:
+ * {Number} The closest server supported zoom.
+ */
+ getServerZoom: function() {
+ return this.map.getZoomForResolution(this.getServerResolution());
+ },
+
+ /**
+ * 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.)) * (scale - 1);
+ var y = (lcY - (size.h / 2.)) * (scale - 1);
+
+ this.div.style.left = x + '%';
+ this.div.style.top = y + '%';
+ },
+
+
+ /**
+ * Method: getResolutionScale
+ * Return the value by which the layer is currently scaled.
+ *
+ * Returns:
+ * {Number} The resolution scale.
+ */
+ getResolutionScale: function() {
+ return parseInt(this.div.style.width, 10) / 100;
+ },
+
/**
* Method: moveByPx
* Move the layer based on pixel vector.
@@ -471,7 +584,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
* bounds - {}
*/
initGriddedTiles:function(bounds) {
-
+
// 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
@@ -482,7 +595,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
Math.max(1, 2 * this.buffer);
var origin = this.getTileOrigin();
- var resolution = this.map.getResolution();
+ var resolution = this.getServerResolution();
var tileLayout = this.calculateGridLayout(bounds, origin, resolution);
@@ -504,7 +617,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);
-
+
do {
var row = this.grid[rowidx++];
@@ -713,17 +826,25 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
moveGriddedTiles: function() {
var shifted = true;
var buffer = this.buffer || 1;
- var tlLayer = this.grid[0][0].position;
+ 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);
- if (tlViewPort.x > -this.tileSize.w * (buffer - 1)) {
+ var tileSize = this.tileSize.clone();
+ tileSize.w *= scale;
+ tileSize.h *= scale;
+ if (tlViewPort.x > -tileSize.w * (buffer - 1)) {
this.shiftColumn(true);
- } else if (tlViewPort.x < -this.tileSize.w * buffer) {
+ } else if (tlViewPort.x < -tileSize.w * buffer) {
this.shiftColumn(false);
- } else if (tlViewPort.y > -this.tileSize.h * (buffer - 1)) {
+ } else if (tlViewPort.y > -tileSize.h * (buffer - 1)) {
this.shiftRow(true);
- } else if (tlViewPort.y < -this.tileSize.h * buffer) {
+ } else if (tlViewPort.y < -tileSize.h * buffer) {
this.shiftRow(false);
} else {
shifted = false;
@@ -749,7 +870,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
var grid = this.grid;
var modelRow = grid[modelRowIndex];
- var resolution = this.map.getResolution();
+ var resolution = this.getServerResolution();
var deltaY = (prepend) ? -this.tileSize.h : this.tileSize.h;
var deltaLat = resolution * -deltaY;
@@ -782,7 +903,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
*/
shiftColumn: function(prepend) {
var deltaX = (prepend) ? -this.tileSize.w : this.tileSize.w;
- var resolution = this.map.getResolution();
+ var resolution = this.getServerResolution();
var deltaLon = resolution * deltaX;
for (var i=0, len=this.grid.length; i can include
+ * resolutions that the server supports and that you don't want to
+ * provide with this layer; you can also look at , which is
+ * an alternative to for that specific purpose.
+ * (b) The map can work with resolutions that aren't supported by
+ * the server, i.e. that aren't in . When the
+ * map is displayed in such a resolution data for the closest
+ * server-supported resolution is loaded and the layer div is
+ * stretched as necessary.
*/
serverResolutions: null,
@@ -162,12 +171,12 @@ OpenLayers.Layer.TMS = OpenLayers.Class(OpenLayers.Layer.Grid, {
*/
getURL: function (bounds) {
bounds = this.adjustBounds(bounds);
- var res = this.map.getResolution();
+ var res = this.getServerResolution();
var x = Math.round((bounds.left - this.tileOrigin.lon) / (res * this.tileSize.w));
var y = Math.round((bounds.bottom - this.tileOrigin.lat) / (res * this.tileSize.h));
var z = this.serverResolutions != null ?
OpenLayers.Util.indexOf(this.serverResolutions, res) :
- this.map.getZoom() + this.zoomOffset;
+ this.getServerZoom() + this.zoomOffset;
var path = this.serviceVersion + "/" + this.layername + "/" + z + "/" + x + "/" + y + "." + this.type;
var url = this.url;
if (OpenLayers.Util.isArray(url)) {
diff --git a/lib/OpenLayers/Layer/TileCache.js b/lib/OpenLayers/Layer/TileCache.js
index 3510af5c5f..36b1bd2e94 100644
--- a/lib/OpenLayers/Layer/TileCache.js
+++ b/lib/OpenLayers/Layer/TileCache.js
@@ -37,8 +37,15 @@ OpenLayers.Layer.TileCache = OpenLayers.Class(OpenLayers.Layer.Grid, {
/**
* APIProperty: serverResolutions
- * {Array} A list of all resolutions available on the server. Only set this
- * property if the map resolutions differs from the server.
+ * {Array} A list of all resolutions available on the server. Only set this
+ * property if the map resolutions differ from the server. This
+ * property serves two purposes. (a) can include
+ * resolutions that the server supports and that you don't want to
+ * provide with this layer. (b) The map can work with resolutions
+ * that aren't supported by the server, i.e. that aren't in
+ * . When the map is displayed in such a resolution
+ * data for the closest server-supported resolution is loaded and the
+ * layer div is stretched as necessary.
*/
serverResolutions: null,
@@ -102,7 +109,7 @@ OpenLayers.Layer.TileCache = OpenLayers.Class(OpenLayers.Layer.Grid, {
* passed-in bounds and appropriate tile size specified as parameters.
*/
getURL: function(bounds) {
- var res = this.map.getResolution();
+ var res = this.getServerResolution();
var bbox = this.maxExtent;
var size = this.tileSize;
var tileX = Math.round((bounds.left - bbox.left) / (res * size.w));
diff --git a/lib/OpenLayers/Layer/WMTS.js b/lib/OpenLayers/Layer/WMTS.js
index 0e6045bf59..54d6d55be0 100644
--- a/lib/OpenLayers/Layer/WMTS.js
+++ b/lib/OpenLayers/Layer/WMTS.js
@@ -150,7 +150,23 @@ OpenLayers.Layer.WMTS = OpenLayers.Class(OpenLayers.Layer.Grid, {
* the property. Defaults to 0 (no zoom offset).
*/
zoomOffset: 0,
-
+
+ /**
+ * APIProperty: serverResolutions
+ * {Array} A list of all resolutions available on the server. Only set this
+ * property if the map resolutions differ from the server. This
+ * property serves two purposes. (a) can include
+ * resolutions that the server supports and that you don't want to
+ * provide with this layer; you can also look at , which is
+ * an alternative to for that specific purpose.
+ * (b) The map can work with resolutions that aren't supported by
+ * the server, i.e. that aren't in . When the
+ * map is displayed in such a resolution data for the closest
+ * server-supported resolution is loaded and the layer div is
+ * stretched as necessary.
+ */
+ serverResolutions: null,
+
/**
* Property: formatSuffixMap
* {Object} a map between WMTS 'format' request parameter and tile image file suffix
@@ -308,6 +324,17 @@ OpenLayers.Layer.WMTS = OpenLayers.Class(OpenLayers.Layer.Grid, {
// copy/set any non-init, non-simple values here
return obj;
},
+
+ /**
+ * Method: getIdentifier
+ * Get the current index in the matrixIds array.
+ */
+ getIdentifier: function() {
+ return this.serverResolutions != null ?
+ OpenLayers.Util.indexOf(this.serverResolutions,
+ this.getServerResolution()) :
+ this.getServerZoom() + this.zoomOffset;
+ },
/**
* Method: getMatrix
@@ -316,7 +343,7 @@ OpenLayers.Layer.WMTS = OpenLayers.Class(OpenLayers.Layer.Grid, {
getMatrix: function() {
var matrix;
if (!this.matrixIds || this.matrixIds.length === 0) {
- matrix = {identifier: this.map.getZoom() + this.zoomOffset};
+ matrix = {identifier: this.getIdentifier()};
} else {
// get appropriate matrix given the map scale if possible
if ("scaleDenominator" in this.matrixIds[0]) {
@@ -324,7 +351,7 @@ OpenLayers.Layer.WMTS = OpenLayers.Class(OpenLayers.Layer.Grid, {
var denom =
OpenLayers.METERS_PER_INCH *
OpenLayers.INCHES_PER_UNIT[this.units] *
- this.map.getResolution() / 0.28E-3;
+ this.getServerResolution() / 0.28E-3;
var diff = Number.POSITIVE_INFINITY;
var delta;
for (var i=0, ii=this.matrixIds.length; i can include
+ * resolutions that the server supports and that you don't want to
+ * provide with this layer; you can also look at , which is
+ * an alternative to for that specific purpose.
+ * (b) The map can work with resolutions that aren't supported by
+ * the server, i.e. that aren't in . When the
+ * map is displayed in such a resolution data for the closest
+ * server-supported resolution is loaded and the layer div is
+ * stretched as necessary.
*/
serverResolutions: null,
@@ -139,7 +148,7 @@ OpenLayers.Layer.XYZ = OpenLayers.Class(OpenLayers.Layer.Grid, {
* {Object} - an object with x, y and z properties.
*/
getXYZ: function(bounds) {
- var res = this.map.getResolution();
+ var res = this.getServerResolution();
var x = Math.round((bounds.left - this.maxExtent.left) /
(res * this.tileSize.w));
var y = Math.round((this.maxExtent.top - bounds.top) /
@@ -147,7 +156,7 @@ OpenLayers.Layer.XYZ = OpenLayers.Class(OpenLayers.Layer.Grid, {
var resolutions = this.serverResolutions || this.resolutions;
var z = this.zoomOffset == 0 ?
OpenLayers.Util.indexOf(resolutions, res) :
- this.map.getZoom() + this.zoomOffset;
+ this.getServerZoom() + this.zoomOffset;
var limit = Math.pow(2, z);
if (this.wrapDateLine)
diff --git a/lib/OpenLayers/Map.js b/lib/OpenLayers/Map.js
index 528f7a032d..3c83d56732 100644
--- a/lib/OpenLayers/Map.js
+++ b/lib/OpenLayers/Map.js
@@ -520,6 +520,8 @@ OpenLayers.Map = OpenLayers.Class({
// the layerContainerDiv is the one that holds all the layers
id = this.id + "_OpenLayers_Container";
this.layerContainerDiv = OpenLayers.Util.createDiv(id);
+ this.layerContainerDiv.style.width = '100px';
+ this.layerContainerDiv.style.height = '100px';
this.layerContainerDiv.style.zIndex=this.Z_INDEX_BASE['Popup']-1;
this.eventsDiv.appendChild(this.layerContainerDiv);
diff --git a/lib/OpenLayers/Tile/BackBufferable.js b/lib/OpenLayers/Tile/BackBufferable.js
index db897c2f7c..689d7386d5 100644
--- a/lib/OpenLayers/Tile/BackBufferable.js
+++ b/lib/OpenLayers/Tile/BackBufferable.js
@@ -90,6 +90,22 @@ OpenLayers.Tile.BackBufferable = OpenLayers.Class(OpenLayers.Tile, {
* Returns:
* {DOMElement} A copy of the tile's markup.
*/
+
+ /**
+ * Method: getTileResolution
+ * Get the tile's actual resolution.
+ *
+ * Returns:
+ * {Number}
+ */
+ getTileResolution: function() {
+ var layer = this.layer,
+ map = layer.map,
+ mapResolution = map.getResolution();
+ return layer.getServerResolution ?
+ layer.getServerResolution(mapResolution) :
+ mapResolution;
+ },
/**
* Method: setBackBufferData
@@ -99,7 +115,7 @@ OpenLayers.Tile.BackBufferable = OpenLayers.Class(OpenLayers.Tile, {
setBackBufferData: function() {
this.backBufferData = OpenLayers.Util.extend(this.backBufferData, {
bounds: this.bounds,
- resolution: this.layer.map.getResolution()
+ resolution: this.getTileResolution()
});
},
@@ -119,8 +135,9 @@ OpenLayers.Tile.BackBufferable = OpenLayers.Class(OpenLayers.Tile, {
data = this.backBufferData,
tile = this.getTile(),
backBuffer = data.tile,
- resolution = data.resolution,
- ratio = resolution ? resolution / map.getResolution() : 1,
+ prevResolution = data.resolution,
+ nextResolution = this.getTileResolution(),
+ ratio = prevResolution ? prevResolution / nextResolution : 1,
// Cases where we don't position and return a back buffer, but only
// update backBufferData and return undefined:
@@ -131,7 +148,8 @@ OpenLayers.Tile.BackBufferable = OpenLayers.Class(OpenLayers.Tile, {
// (3) we don't have a tile available that we could use as buffer
noTile = !(tile && tile.childNodes.length > 0),
// (4) no backbuffer is displayed for a tile that's still loading
- noBackBuffer = !backBuffer && this.isLoading;
+ noBackBuffer = !backBuffer && this.isLoading;
+
if (notNeeded || noParent || noTile || noBackBuffer) {
this.setBackBufferData();
return;
@@ -139,26 +157,26 @@ OpenLayers.Tile.BackBufferable = OpenLayers.Class(OpenLayers.Tile, {
// Create a back buffer tile and add it to the DOM
if (!backBuffer) {
- backBuffer = this.createBackBuffer();
+ backBuffer = this.insertBackBuffer();
// some browsers fire the onload event before the image is
// displayed, so we keep the buffer until the whole layer finished
// loading to avoid visual glitches
layer.events.register("loadend", this, this.resetBackBuffer);
data.tile = backBuffer;
- layer.div.insertBefore(backBuffer, tile);
}
// Position the back buffer now that we have one
var lonLat = {lon: data.bounds.left, lat: data.bounds.top},
- position = map.getPixelFromLonLat(lonLat),
+ position = layer.getViewPortPxFromLonLat(lonLat, nextResolution),
containerStyle = map.layerContainerDiv.style,
leftOffset = parseInt(containerStyle.left, 10),
topOffset = parseInt(containerStyle.top, 10),
style = backBuffer.style;
- style.left = (position.x - leftOffset) + "px";
- style.top = (position.y - topOffset) + "px";
- style.width = (this.size.w * ratio) + "px";
- style.height = (this.size.h * ratio) + "px";
+
+ style.left = (position.x - leftOffset) + "%";
+ style.top = (position.y - topOffset) + "%";
+ style.width = (this.size.w * ratio) + "%";
+ style.height = (this.size.h * ratio) + "%";
return backBuffer;
},
diff --git a/lib/OpenLayers/Tile/Image.js b/lib/OpenLayers/Tile/Image.js
index ff2b6ace99..c3037256b6 100644
--- a/lib/OpenLayers/Tile/Image.js
+++ b/lib/OpenLayers/Tile/Image.js
@@ -187,10 +187,10 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile.BackBufferable, {
*/
positionTile: function() {
var style = this.frame.style;
- style.left = this.position.x + "px";
- style.top = this.position.y + "px";
- style.width = this.size.w + "px";
- style.height = this.size.h + "px";
+ style.left = this.position.x + "%";
+ style.top = this.position.y + "%";
+ style.width = this.size.w + "%";
+ style.height = this.size.h + "%";
},
/**
@@ -320,14 +320,16 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile.BackBufferable, {
},
/**
- * Method: createBackBuffer
- * Create a copy of this tile's markup for the 's backBufferDiv
+ * Method: insertBackBuffer
+ * Create a copy of this tile's markup and insert it to the layer
+ * div.
*
* Returns:
- * {DOMElement} a clone of the tile content
+ * {DOMElement} The back buffer.
*/
- createBackBuffer: function() {
+ insertBackBuffer: function() {
var frame = this.frame.cloneNode(false);
+ this.layer.div.insertBefore(frame, this.frame);
frame.appendChild(this.imgDiv);
this.imgDiv = null;
return frame;
diff --git a/tests/Layer/ArcGIS93Rest.html b/tests/Layer/ArcGIS93Rest.html
index 184a9f7c01..ff11955dbb 100644
--- a/tests/Layer/ArcGIS93Rest.html
+++ b/tests/Layer/ArcGIS93Rest.html
@@ -75,8 +75,8 @@
t.eq( tile.url,
url + "?" + OpenLayers.Util.getParameterString(tParams),
"image src is created correctly via addtile" );
- t.eq( tile.frame.style.top, "6px", "image top is set correctly via addtile" );
- t.eq( tile.frame.style.left, "5px", "image top is set correctly via addtile" );
+ t.eq( tile.frame.style.top, "6%", "image top is set correctly via addtile" );
+ t.eq( tile.frame.style.left, "5%", "image top is set correctly via addtile" );
var firstChild = layer.div.firstChild.firstChild;
t.eq( firstChild.nodeName.toLowerCase(), "img", "div first child is an image object" );
diff --git a/tests/Layer/Grid.html b/tests/Layer/Grid.html
index d64dfca90b..fd8afb6e9d 100644
--- a/tests/Layer/Grid.html
+++ b/tests/Layer/Grid.html
@@ -624,6 +624,195 @@
t.eq( layer.tileSize, null, "layer.tileSize is null after destroy" );
}
+ function test_getServerResolution(t) {
+
+ t.plan(4);
+
+ var layer = new OpenLayers.Layer.Grid('', '', {}, {});
+ var res;
+
+ res = layer.getServerResolution(1);
+ t.eq(res, 1, '[1] getServerResolution return value is correct');
+
+ layer.serverResolutions = [2, 1];
+ res = layer.getServerResolution(1);
+ t.eq(res, 1, '[2] getServerResolution return value is correct');
+
+ layer.serverResolutions = [2];
+ res = layer.getServerResolution(1);
+ t.eq(res, 2, '[3] getServerResolution return value is correct');
+
+ var exc;
+ layer.serverResolutions = [0.5];
+ try {
+ res = layer.getServerResolution(1);
+ } catch(e) {
+ exc = e;
+ }
+ t.ok(exc != undefined, '[4] getServerResolution generates exception');
+ }
+
+ function test_getServerZoom(t) {
+
+ t.plan(5);
+
+ var resolution, zoom;
+ var map = new OpenLayers.Map('map', {
+ resolutions: [8, 4, 2, 1, 0.5],
+ getResolution: function() {
+ return resolution;
+ }
+ });
+ var layer = new OpenLayers.Layer.WMS('', '', {}, {isBaseLayer: true});
+ map.addLayer(layer);
+
+ resolution = 8;
+ zoom = layer.getServerZoom();
+ t.eq(zoom, 0, '[1] getServerZoom return value is correct');
+
+ resolution = 4;
+ zoom = layer.getServerZoom();
+ t.eq(zoom, 1, '[2] getServerZoom return value is correct');
+
+ layer.serverResolutions = [2, 1];
+ resolution = 1;
+ zoom = layer.getServerZoom();
+ t.eq(zoom, 3, '[3] getServerZoom return value is correct');
+
+ layer.serverResolutions = [2];
+ resolution = 0.5;
+ zoom = layer.getServerZoom();
+ t.eq(zoom, 2, '[4] getServerZoom return value is correct');
+
+ var exc;
+ layer.serverResolutions = [0.5];
+ resolution = 1;
+ try {
+ zoom = layer.getServerZoom();
+ } catch(e) {
+ exc = e;
+ }
+ t.ok(exc != undefined, '[4] getServerZoom generates exception');
+
+ map.destroy();
+ }
+
+ function test_moveTo_scale(t) {
+
+ t.plan(11);
+
+ var map = new OpenLayers.Map('map', {
+ resolutions: [32, 16, 8, 4, 2, 1]
+ });
+ var layer = new OpenLayers.Layer.WMS('', '', {}, {
+ isBaseLayer: true,
+ serverResolutions: [32, 16, 8]
+ });
+ map.addLayer(layer);
+
+ // initial resolution is 8
+ map.setCenter(new OpenLayers.LonLat(0, 0), 2);
+
+ // test initial conditions
+ t.eq(layer.div.style.width, '100%', 'layer div scale is 1');
+
+ // change from resolution 8 to 4
+ map.zoomTo(3);
+ t.eq(layer.div.style.width, '200%', '[8->4] layer div scale is 2');
+
+ // change from resolution 8 to 2
+ map.zoomTo(2); map.zoomTo(4);
+ t.eq(layer.div.style.width, '400%', '[8->2] layer div scale is 4');
+
+ // change from resolution 8 to 1
+ map.zoomTo(2); map.zoomTo(5);
+ t.eq(layer.div.style.width, '800%', '[8->1] layer div scale is 8');
+
+ // change from resolution 4 to 2
+ map.zoomTo(3); map.zoomTo(4);
+ t.eq(layer.div.style.width, '400%', '[4->2] layer div scale is 4');
+
+ // change from resolution 4 to 1
+ map.zoomTo(3); map.zoomTo(5);
+ t.eq(layer.div.style.width, '800%', '[4->1] layer div scale is 8');
+
+ // change from resolution 2 to 1
+ map.zoomTo(4); map.zoomTo(5);
+ t.eq(layer.div.style.width, '800%', '[2->1] layer div scale is 8');
+
+ // change from resolution 1 to 2
+ map.zoomTo(5); map.zoomTo(4);
+ t.eq(layer.div.style.width, '400%', '[1->2] layer div scale is 4');
+
+ // change from resolution 1 to 4
+ map.zoomTo(5); map.zoomTo(3);
+ t.eq(layer.div.style.width, '200%', '[1->4] layer div scale is 2');
+
+ // change from resolution 1 to 8
+ map.zoomTo(5); map.zoomTo(2);
+ t.eq(layer.div.style.width, '100%', '[1->8] layer div scale is 1');
+
+ // change from resolution 1 to 16
+ map.zoomTo(5); map.zoomTo(1);
+ t.eq(layer.div.style.width, '100%', '[1->16] layer div scale is 1');
+
+ map.destroy();
+ }
+
+ function test_transformDiv(t) {
+
+ t.plan(8);
+
+ var map = new OpenLayers.Map('map4');
+ var layer = new OpenLayers.Layer.WMS('', '', {}, {
+ isBaseLayer: true
+ });
+ map.addLayer(layer);
+ map.zoomToMaxExtent();
+
+ // the layer container's dimensions are 100px width 100px height
+ // the position of the viewport center is 384, 256
+
+ layer.transformDiv(2);
+
+ t.eq(layer.div.style.width, '200%', '[1] layer div has correct width');
+ t.eq(layer.div.style.height, '200%', '[1] layer div has correct height');
+
+ t.eq(layer.div.style.left, '-384%', '[1] layer div has correct left');
+ t.eq(layer.div.style.top, '-256%', '[1] layer div has correct top');
+
+ // now move the layer container and test again
+
+ map.layerContainerDiv.style.left = '-1024px';
+ map.layerContainerDiv.style.top = '768px';
+
+ layer.transformDiv(2);
+
+ t.eq(layer.div.style.width, '200%', '[2] layer div has correct width');
+ t.eq(layer.div.style.height, '200%', '[2] layer div has correct height');
+
+ t.eq(layer.div.style.left, '-1408%', '[2] layer div has correct left');
+ t.eq(layer.div.style.top, '512%', '[2] layer div has correct top');
+
+ map.destroy();
+ }
+
+ function test_getResolutionScale(t) {
+ t.plan(1);
+
+ var map = new OpenLayers.Map('map');
+ var layer = new OpenLayers.Layer.WMS('', '', {}, {
+ isBaseLayer: true
+ });
+ map.addLayer(layer);
+ map.zoomToMaxExtent();
+
+ layer.transformDiv(2);
+ var scale = layer.getResolutionScale();
+ t.eq(scale, 2, 'getResolutionScale returns correct value');
+
+ map.destroy();
+ }
@@ -631,5 +820,6 @@
+