Commit tile-reuse branch back to trunk. This branch offers numerous performance
improvements in the form of reduced memory use and lower element creating costs, hopefully making the OpenLayers code more usable in internet explorer as well as less of a memory hog in Firefox and other browsers. Additionally, a buffer is available around the main map grid which allows tiles to be loaded outside of the viewing area for faster dragging. git-svn-id: http://svn.openlayers.org/trunk/openlayers@1137 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
@@ -26,6 +26,10 @@ OpenLayers.Control.LayerSwitcher.prototype =
|
||||
/** @type Array */
|
||||
baseLayerInputs: null,
|
||||
|
||||
|
||||
/** @type DOMElement */
|
||||
dataLbl: null,
|
||||
|
||||
/** @type DOMElement */
|
||||
dataLayersDiv: null,
|
||||
|
||||
@@ -223,8 +227,6 @@ OpenLayers.Control.LayerSwitcher.prototype =
|
||||
this.div.style.width = "0px";
|
||||
this.div.style.height = "0px";
|
||||
|
||||
// this.div.style.backgroundColor = "transparent";
|
||||
|
||||
this.showControls(true);
|
||||
|
||||
if (e != null) {
|
||||
@@ -331,7 +333,7 @@ OpenLayers.Control.LayerSwitcher.prototype =
|
||||
// maximize button div
|
||||
var img = imgLocation + 'layer-switcher-maximize.png';
|
||||
this.maximizeDiv = OpenLayers.Util.createAlphaImageDiv(
|
||||
"OpenLayers_Control_ResizeDiv",
|
||||
"OpenLayers_Control_MaximizeDiv",
|
||||
null,
|
||||
sz,
|
||||
img,
|
||||
@@ -350,7 +352,7 @@ OpenLayers.Control.LayerSwitcher.prototype =
|
||||
var img = imgLocation + 'layer-switcher-minimize.png';
|
||||
var sz = new OpenLayers.Size(18,18);
|
||||
this.minimizeDiv = OpenLayers.Util.createAlphaImageDiv(
|
||||
"OpenLayers_Control_ResizeDiv",
|
||||
"OpenLayers_Control_MinimizeDiv",
|
||||
null,
|
||||
sz,
|
||||
img,
|
||||
|
||||
@@ -30,6 +30,11 @@ OpenLayers.Layer.prototype = {
|
||||
*/
|
||||
isBaseLayer: false,
|
||||
|
||||
/** asserts whether or not the layer's images have an alpha channel
|
||||
*
|
||||
* @type boolean */
|
||||
alpha: false,
|
||||
|
||||
// OPTIONS
|
||||
|
||||
/** @type Array */
|
||||
|
||||
@@ -20,11 +20,8 @@ OpenLayers.Layer.Grid.prototype =
|
||||
* @type Array(Array) */
|
||||
grid: null,
|
||||
|
||||
/** asserts whether or not the layer's images have an alpha channel
|
||||
*
|
||||
* @type boolean */
|
||||
alpha: false,
|
||||
|
||||
/** @type Integer */
|
||||
buffer: 2,
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
@@ -37,6 +34,7 @@ OpenLayers.Layer.Grid.prototype =
|
||||
initialize: function(name, url, params, options) {
|
||||
OpenLayers.Layer.HTTPRequest.prototype.initialize.apply(this,
|
||||
arguments);
|
||||
this.grid = new Array();
|
||||
},
|
||||
|
||||
/** on destroy, clear the grid.
|
||||
@@ -132,37 +130,33 @@ OpenLayers.Layer.Grid.prototype =
|
||||
*
|
||||
* @param {OpenLayers.Bounds} bounds
|
||||
* @param {Boolean} zoomChanged
|
||||
* @param {Boolean} minor
|
||||
* @param {Boolean} dragging
|
||||
*/
|
||||
moveTo:function(bounds, zoomChanged, minor) {
|
||||
moveTo:function(bounds, zoomChanged, dragging) {
|
||||
if (bounds == null) {
|
||||
bounds = this.map.getExtent();
|
||||
}
|
||||
if (bounds != null) {
|
||||
if (!this.getVisibility()) {
|
||||
if (zoomChanged) {
|
||||
//now clear out the old grid and start a new one
|
||||
this.clearGrid();
|
||||
this.grid = null;
|
||||
// FIX ME FIX ME FIX ME -- should be this.hideGrid() basically
|
||||
}
|
||||
} else {
|
||||
if (!this.grid || zoomChanged) {
|
||||
this._initTiles();
|
||||
} else if (this.getGridBounds().containsBounds(bounds, true) == false) {
|
||||
} else if (!this.grid.length || zoomChanged
|
||||
|| !this.getGridBounds().containsBounds(bounds, true)) {
|
||||
this._initTiles();
|
||||
} else {
|
||||
var i = 0;
|
||||
while (this.getGridBounds().bottom > bounds.bottom) {
|
||||
this.insertRow(false);
|
||||
}
|
||||
while (this.getGridBounds().left > bounds.left) {
|
||||
this.insertColumn(true);
|
||||
}
|
||||
while (this.getGridBounds().top < bounds.top) {
|
||||
this.insertRow(true);
|
||||
}
|
||||
while (this.getGridBounds().right < bounds.right) {
|
||||
this.insertColumn(false);
|
||||
while (true) {
|
||||
var topLeft = this.map.getViewPortPxFromLayerPx( this.grid[0][0].position );
|
||||
if (topLeft.x > -this.tileSize.w * (this.buffer - 1)) {
|
||||
this.shiftColumn(true);
|
||||
} else if (topLeft.x < -this.tileSize.w * this.buffer) {
|
||||
this.shiftColumn(false);
|
||||
} else if (topLeft.y > -this.tileSize.w * (this.buffer - 1)) {
|
||||
this.shiftRow(true);
|
||||
} else if (topLeft.y < -this.tileSize.h * this.buffer) {
|
||||
this.shiftRow(false);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -193,14 +187,6 @@ OpenLayers.Layer.Grid.prototype =
|
||||
*
|
||||
*/
|
||||
_initTiles:function() {
|
||||
|
||||
//first of all, clear out the main div
|
||||
this.div.innerHTML = "";
|
||||
|
||||
//now clear out the old grid and start a new one
|
||||
this.clearGrid();
|
||||
this.grid = new Array();
|
||||
|
||||
var viewSize = this.map.getSize();
|
||||
var bounds = this.map.getExtent();
|
||||
var extent = this.map.getMaxExtent();
|
||||
@@ -209,13 +195,13 @@ OpenLayers.Layer.Grid.prototype =
|
||||
var tilelat = resolution * this.tileSize.h;
|
||||
|
||||
var offsetlon = bounds.left - extent.left;
|
||||
var tilecol = Math.floor(offsetlon/tilelon);
|
||||
var tilecol = Math.floor(offsetlon/tilelon) - this.buffer;
|
||||
var tilecolremain = offsetlon/tilelon - tilecol;
|
||||
var tileoffsetx = -tilecolremain * this.tileSize.w;
|
||||
var tileoffsetlon = extent.left + tilecol * tilelon;
|
||||
|
||||
var offsetlat = bounds.top - (extent.bottom + tilelat);
|
||||
var tilerow = Math.ceil(offsetlat/tilelat);
|
||||
var tilerow = Math.ceil(offsetlat/tilelat) + this.buffer;
|
||||
var tilerowremain = tilerow - offsetlat/tilelat;
|
||||
var tileoffsety = -tilerowremain * this.tileSize.h;
|
||||
var tileoffsetlat = extent.bottom + tilerow * tilelat;
|
||||
@@ -228,12 +214,24 @@ OpenLayers.Layer.Grid.prototype =
|
||||
var startX = tileoffsetx;
|
||||
var startLon = tileoffsetlon;
|
||||
|
||||
var newGrid = (this.grid.length == 0);
|
||||
var rowidx = 0;
|
||||
|
||||
do {
|
||||
var row = new Array();
|
||||
var row;
|
||||
|
||||
if (newGrid) {
|
||||
row = new Array();
|
||||
this.grid.push(row);
|
||||
} else {
|
||||
row = this.grid[rowidx++];
|
||||
}
|
||||
|
||||
tileoffsetlon = startLon;
|
||||
tileoffsetx = startX;
|
||||
|
||||
var colidx = 0;
|
||||
|
||||
do {
|
||||
var tileBounds = new OpenLayers.Bounds(tileoffsetlon,
|
||||
tileoffsetlat,
|
||||
@@ -247,19 +245,24 @@ OpenLayers.Layer.Grid.prototype =
|
||||
y -= parseInt(this.map.layerContainerDiv.style.top);
|
||||
|
||||
var px = new OpenLayers.Pixel(x, y);
|
||||
var tile;
|
||||
|
||||
var tile = this.addTile(tileBounds, px);
|
||||
|
||||
tile.draw(this.alpha);
|
||||
if (newGrid) {
|
||||
tile = this.addTile(tileBounds, px);
|
||||
tile.draw();
|
||||
row.push(tile);
|
||||
} else {
|
||||
tile = row[colidx++];
|
||||
tile.moveTo(tileBounds, px);
|
||||
}
|
||||
|
||||
tileoffsetlon += tilelon;
|
||||
tileoffsetx += this.tileSize.w;
|
||||
} while (tileoffsetlon < bounds.right)
|
||||
} while (tileoffsetlon <= bounds.right + tilelon * this.buffer)
|
||||
|
||||
tileoffsetlat -= tilelat;
|
||||
tileoffsety += this.tileSize.h;
|
||||
} while(tileoffsetlat > bounds.bottom - tilelat)
|
||||
} while(tileoffsetlat >= bounds.bottom - tilelat * this.buffer)
|
||||
|
||||
},
|
||||
|
||||
@@ -376,16 +379,16 @@ OpenLayers.Layer.Grid.prototype =
|
||||
* @param {Boolean} prepend if true, prepend to beginning.
|
||||
* if false, then append to end
|
||||
*/
|
||||
insertRow:function(prepend) {
|
||||
shiftRow:function(prepend) {
|
||||
var modelRowIndex = (prepend) ? 0 : (this.grid.length - 1);
|
||||
var modelRow = this.grid[modelRowIndex];
|
||||
|
||||
var newRow = new Array();
|
||||
|
||||
var resolution = this.map.getResolution();
|
||||
var deltaY = (prepend) ? -this.tileSize.h : this.tileSize.h;
|
||||
var deltaLat = resolution * -deltaY;
|
||||
|
||||
var row = (prepend) ? this.grid.pop() : this.grid.shift();
|
||||
|
||||
for (var i=0; i < modelRow.length; i++) {
|
||||
var modelTile = modelRow[i];
|
||||
var bounds = modelTile.bounds.clone();
|
||||
@@ -393,17 +396,13 @@ OpenLayers.Layer.Grid.prototype =
|
||||
bounds.bottom = bounds.bottom + deltaLat;
|
||||
bounds.top = bounds.top + deltaLat;
|
||||
position.y = position.y + deltaY;
|
||||
var newTile = this.addTile(bounds, position);
|
||||
newTile.draw(this.alpha);
|
||||
newRow.push(newTile);
|
||||
row[i].moveTo(bounds, position);
|
||||
}
|
||||
|
||||
if (newRow.length>0){
|
||||
if (prepend) {
|
||||
this.grid.unshift(newRow);
|
||||
this.grid.unshift(row);
|
||||
} else {
|
||||
this.grid.push(newRow);
|
||||
}
|
||||
this.grid.push(row);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -413,15 +412,14 @@ OpenLayers.Layer.Grid.prototype =
|
||||
* @param {Boolean} prepend if true, prepend to beginning.
|
||||
* if false, then append to end
|
||||
*/
|
||||
insertColumn:function(prepend) {
|
||||
var modelCellIndex;
|
||||
shiftColumn: function(prepend) {
|
||||
var deltaX = (prepend) ? -this.tileSize.w : this.tileSize.w;
|
||||
var resolution = this.map.getResolution();
|
||||
var deltaLon = resolution * deltaX;
|
||||
|
||||
for (var i=0; i<this.grid.length; i++) {
|
||||
var row = this.grid[i];
|
||||
modelTileIndex = (prepend) ? 0 : (row.length - 1);
|
||||
var modelTileIndex = (prepend) ? 0 : (row.length - 1);
|
||||
var modelTile = row[modelTileIndex];
|
||||
|
||||
var bounds = modelTile.bounds.clone();
|
||||
@@ -429,13 +427,13 @@ OpenLayers.Layer.Grid.prototype =
|
||||
bounds.left = bounds.left + deltaLon;
|
||||
bounds.right = bounds.right + deltaLon;
|
||||
position.x = position.x + deltaX;
|
||||
var newTile = this.addTile(bounds, position);
|
||||
newTile.draw(this.alpha);
|
||||
|
||||
var tile = prepend ? this.grid[i].pop() : this.grid[i].shift()
|
||||
tile.moveTo(bounds, position);
|
||||
if (prepend) {
|
||||
row = row.unshift(newTile);
|
||||
this.grid[i].unshift(tile);
|
||||
} else {
|
||||
row = row.push(newTile);
|
||||
this.grid[i].push(tile);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -44,7 +44,8 @@ OpenLayers.Layer.KaMap.prototype =
|
||||
);
|
||||
}
|
||||
},
|
||||
addTile:function(bounds,position) {
|
||||
|
||||
getURL:function(bounds) {
|
||||
var zoom = this.map.getZoom();
|
||||
var maxRes = this.map.maxResolution;
|
||||
var mapRes = this.map.getResolution();
|
||||
@@ -53,14 +54,19 @@ OpenLayers.Layer.KaMap.prototype =
|
||||
var cellSize = new OpenLayers.Size(mapRes*this.tileSize.w, mapRes*this.tileSize.h);
|
||||
var pX = Math.round(((bounds.left) / cellSize.w) * this.tileSize.w);
|
||||
var pY = -Math.round(((bounds.top) / cellSize.h) * this.tileSize.h);
|
||||
var url = this.getFullRequestString(
|
||||
return this.getFullRequestString(
|
||||
{ t: pY,
|
||||
l: pX,
|
||||
s: scale
|
||||
});
|
||||
},
|
||||
|
||||
addTile:function(bounds,position) {
|
||||
var url = this.getURL(bounds);
|
||||
return new OpenLayers.Tile.Image(this, position, bounds,
|
||||
url, this.tileSize);
|
||||
},
|
||||
|
||||
_initTiles:function() {
|
||||
|
||||
//first of all, clear out the main div
|
||||
@@ -112,7 +118,7 @@ OpenLayers.Layer.KaMap.prototype =
|
||||
new OpenLayers.Pixel(tileoffsetx - parseInt(this.map.layerContainerDiv.style.left),
|
||||
tileoffsety - parseInt(this.map.layerContainerDiv.style.top))
|
||||
);
|
||||
tile.draw((this.alpha));
|
||||
tile.draw();
|
||||
row.push(tile);
|
||||
|
||||
tileoffsetlon += tilelon;
|
||||
|
||||
@@ -83,6 +83,13 @@ OpenLayers.Layer.WMS.prototype =
|
||||
return obj;
|
||||
},
|
||||
|
||||
getURL: function (bounds) {
|
||||
return this.getFullRequestString(
|
||||
{BBOX:bounds.toBBOX(),
|
||||
WIDTH:this.tileSize.w,
|
||||
HEIGHT:this.tileSize.h});
|
||||
},
|
||||
|
||||
/**
|
||||
* addTile creates a tile, initializes it, and
|
||||
* adds it to the layer div.
|
||||
@@ -93,16 +100,11 @@ OpenLayers.Layer.WMS.prototype =
|
||||
* @type OpenLayers.Tile.Image
|
||||
*/
|
||||
addTile:function(bounds,position) {
|
||||
url = this.getFullRequestString(
|
||||
{BBOX:bounds.toBBOX(),
|
||||
WIDTH:this.tileSize.w,
|
||||
HEIGHT:this.tileSize.h});
|
||||
|
||||
url = this.getURL(bounds);
|
||||
return new OpenLayers.Tile.Image(this, position, bounds,
|
||||
url, this.tileSize);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Catch changeParams and uppercase the new params to be merged in
|
||||
* before calling changeParams on the super class.
|
||||
|
||||
@@ -38,18 +38,9 @@ OpenLayers.Layer.WorldWind.prototype =
|
||||
}
|
||||
},
|
||||
addTile:function(bounds,position) {
|
||||
var zoom = this.map.getZoom();
|
||||
var extent = this.map.getMaxExtent();
|
||||
zoom = zoom - Math.log(this.map.maxResolution / (this.lzd/512))/Math.log(2);
|
||||
if (this.map.getResolution() <= (this.lzd/512) && zoom <= this.zoomLevels) {
|
||||
var deg = this.lzd/Math.pow(2,zoom);
|
||||
var x = Math.floor((bounds.left - extent.left)/deg);
|
||||
var y = Math.floor((bounds.bottom - extent.bottom)/deg);
|
||||
var url = this.getFullRequestString(
|
||||
{ L: zoom,
|
||||
X: x,
|
||||
Y: y
|
||||
});
|
||||
if (this.map.getResolution() <= (this.lzd/512)
|
||||
&& this.getZoom() <= this.zoomLevels) {
|
||||
|
||||
return new OpenLayers.Tile.Image(this, position, bounds,
|
||||
url, this.tileSize);
|
||||
} else {
|
||||
@@ -62,6 +53,25 @@ OpenLayers.Layer.WorldWind.prototype =
|
||||
}
|
||||
},
|
||||
|
||||
getZoom: function () {
|
||||
var zoom = this.map.getZoom();
|
||||
var extent = this.map.getMaxExtent();
|
||||
zoom = zoom - Math.log(this.map.maxResolution / (this.lzd/512))/Math.log(2);
|
||||
return zoom;
|
||||
},
|
||||
|
||||
getURL: function (bounds) {
|
||||
var deg = this.lzd/Math.pow(2,this.getZoom());
|
||||
var x = Math.floor((bounds.left - extent.left)/deg);
|
||||
var y = Math.floor((bounds.bottom - extent.bottom)/deg);
|
||||
return this.getFullRequestString(
|
||||
{ L: zoom,
|
||||
X: x,
|
||||
Y: y
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
/** @final @type String */
|
||||
CLASS_NAME: "OpenLayers.Layer.WorldWind"
|
||||
});
|
||||
|
||||
@@ -73,6 +73,17 @@ OpenLayers.Tile.prototype = {
|
||||
|
||||
},
|
||||
|
||||
redraw: function () {
|
||||
this.draw();
|
||||
},
|
||||
|
||||
moveTo: function (bounds, position) {
|
||||
this.bounds = bounds.clone();
|
||||
this.position = position.clone();
|
||||
this.redraw();
|
||||
},
|
||||
|
||||
|
||||
/** remove this tile from the ds
|
||||
*/
|
||||
remove:function() {
|
||||
|
||||
@@ -35,23 +35,45 @@ OpenLayers.Tile.Image.prototype =
|
||||
|
||||
/**
|
||||
*/
|
||||
draw:function(transparent) {
|
||||
if (transparent) {
|
||||
draw:function() {
|
||||
if (this.layer.alpha) {
|
||||
this.imgDiv = OpenLayers.Util.createAlphaImageDiv(null,
|
||||
this.position,
|
||||
this.size,
|
||||
this.url,
|
||||
"absolute");
|
||||
"absolute",
|
||||
null,
|
||||
null,
|
||||
true);
|
||||
} else {
|
||||
this.imgDiv = OpenLayers.Util.createImage(null,
|
||||
this.position,
|
||||
this.size,
|
||||
this.url,
|
||||
"absolute");
|
||||
"absolute",
|
||||
null,
|
||||
true);
|
||||
}
|
||||
this.layer.div.appendChild(this.imgDiv);
|
||||
},
|
||||
|
||||
moveTo: function (bounds, position) {
|
||||
this.url = this.layer.getURL(bounds);
|
||||
OpenLayers.Tile.prototype.moveTo.apply(this, arguments);
|
||||
},
|
||||
|
||||
redraw: function () {
|
||||
this.imgDiv.style.display = "none";
|
||||
if (this.layer.alpha) {
|
||||
OpenLayers.Util.modifyAlphaImageDiv(this.imgDiv,
|
||||
null, this.position, this.size, this.url);
|
||||
} else {
|
||||
this.imgDiv.src = this.url;
|
||||
OpenLayers.Util.modifyDOMElement(this.imgDiv,
|
||||
null, this.position, this.size) ;
|
||||
}
|
||||
},
|
||||
|
||||
/** @final @type String */
|
||||
CLASS_NAME: "OpenLayers.Tile.Image"
|
||||
}
|
||||
|
||||
@@ -773,14 +773,25 @@ OpenLayers.Util.createDiv = function(id, px, sz, imgURL, position,
|
||||
* @param {String} imgURL
|
||||
* @param {String} position
|
||||
* @param {String} border
|
||||
* @param {Boolean} delayDisplay
|
||||
*
|
||||
* @returns A DOM Image created with the specified attributes.
|
||||
* @type DOMElement
|
||||
*/
|
||||
OpenLayers.Util.createImage = function(id, px, sz, imgURL, position, border) {
|
||||
OpenLayers.Util.createImage = function(id, px, sz, imgURL, position, border,
|
||||
delayDisplay) {
|
||||
|
||||
image = document.createElement("img");
|
||||
|
||||
if(delayDisplay) {
|
||||
image.style.display = "none";
|
||||
Event.observe(image, "load",
|
||||
OpenLayers.Util.onImageLoad.bindAsEventListener(image));
|
||||
Event.observe(image, "error",
|
||||
OpenLayers.Util.onImageLoadError.bindAsEventListener(image));
|
||||
|
||||
}
|
||||
|
||||
//set special properties
|
||||
image.style.alt = id;
|
||||
image.galleryImg = "no";
|
||||
@@ -797,9 +808,21 @@ OpenLayers.Util.createImage = function(id, px, sz, imgURL, position, border) {
|
||||
}
|
||||
OpenLayers.Util.modifyDOMElement(image, id, px, sz, position, border);
|
||||
|
||||
|
||||
return image;
|
||||
};
|
||||
|
||||
|
||||
OpenLayers.Util.onImageLoad = function() {
|
||||
this.style.backgroundColor = null;
|
||||
this.style.display = "";
|
||||
};
|
||||
|
||||
OpenLayers.Util.onImageLoadError = function() {
|
||||
this.style.backgroundColor = "pink";
|
||||
};
|
||||
|
||||
|
||||
OpenLayers.Util.alphaHack = function() {
|
||||
var arVersion = navigator.appVersion.split("MSIE");
|
||||
var version = parseFloat(arVersion[1]);
|
||||
@@ -852,18 +875,28 @@ OpenLayers.Util.modifyAlphaImageDiv = function(div, id, px, sz, imgURL,
|
||||
* @param {String} position
|
||||
* @param {String} border
|
||||
* @param {String} sizing 'crop', 'scale', or 'image'. Default is "scale"
|
||||
* @param {Boolean} delayDisplay
|
||||
*
|
||||
* @returns A DOM Div created with a DOM Image inside it. If the hack is
|
||||
* needed for transparency in IE, it is added.
|
||||
* @type DOMElement
|
||||
*/
|
||||
OpenLayers.Util.createAlphaImageDiv = function(id, px, sz, imgURL,
|
||||
position, border, sizing) {
|
||||
position, border, sizing, delayDisplay) {
|
||||
|
||||
var div = OpenLayers.Util.createDiv();
|
||||
var img = OpenLayers.Util.createImage();
|
||||
var img = OpenLayers.Util.createImage(null, null, null, null, null, null,
|
||||
false);
|
||||
div.appendChild(img);
|
||||
|
||||
if (delayDisplay) {
|
||||
img.style.display = "none";
|
||||
Event.observe(img, "load",
|
||||
OpenLayers.Util.onImageLoad.bindAsEventListener(div));
|
||||
Event.observe(img, "error",
|
||||
OpenLayers.Util.onImageLoadError.bindAsEventListener(div));
|
||||
}
|
||||
|
||||
OpenLayers.Util.modifyAlphaImageDiv(div, id, px, sz, imgURL,
|
||||
position, border, sizing);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user