diff --git a/src/ol/renderer/canvas/canvastilelayerrenderer.js b/src/ol/renderer/canvas/canvastilelayerrenderer.js index a6e5519ec2..70e528542c 100644 --- a/src/ol/renderer/canvas/canvastilelayerrenderer.js +++ b/src/ol/renderer/canvas/canvastilelayerrenderer.js @@ -10,6 +10,7 @@ goog.require('ol.Extent'); goog.require('ol.Size'); goog.require('ol.Tile'); goog.require('ol.TileCoord'); +goog.require('ol.TileRange'); goog.require('ol.TileState'); goog.require('ol.layer.TileLayer'); goog.require('ol.renderer.Map'); @@ -51,6 +52,18 @@ ol.renderer.canvas.TileLayer = function(mapRenderer, tileLayer) { */ this.transform_ = goog.vec.Mat4.createNumber(); + /** + * @private + * @type {number} + */ + this.renderedCanvasZ_ = NaN; + + /** + * @private + * @type {ol.TileRange} + */ + this.renderedCanvasTileRange_ = null; + /** * @private * @type {Array.} @@ -117,31 +130,63 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = var tileRangeWidth = tileRange.getWidth(); var tileRangeHeight = tileRange.getHeight(); - var canvasSize = new ol.Size( - tileSize.width * tileRangeWidth, tileSize.height * tileRangeHeight); + var canvasWidth = tileSize.width * tileRange.getWidth(); + var canvasHeight = tileSize.height * tileRange.getHeight(); var canvas, context; if (goog.isNull(this.canvas_)) { canvas = /** @type {HTMLCanvasElement} */ (goog.dom.createElement(goog.dom.TagName.CANVAS)); - canvas.width = canvasSize.width; - canvas.height = canvasSize.height; + canvas.width = canvasWidth; + canvas.height = canvasHeight; context = /** @type {CanvasRenderingContext2D} */ (canvas.getContext('2d')); this.canvas_ = canvas; - this.canvasSize_ = canvasSize; this.context_ = context; - this.renderedTiles_ = new Array(tileRangeWidth * tileRangeHeight); + this.renderedCanvasTileRange_ = null; } else { canvas = this.canvas_; context = this.context_; - if (!this.canvasSize_.equals(canvasSize)) { - canvas.width = canvasSize.width; - canvas.height = canvasSize.height; - this.canvasSize_ = canvasSize; - this.renderedTiles_ = new Array(tileRangeWidth * tileRangeHeight); + if (this.canvasSize_.width < canvasWidth || + this.canvasSize_.height < canvasHeight) { + canvas.width = canvasWidth; + canvas.height = canvasHeight; + this.renderedCanvasTileRange_ = null; + } else if (z != this.renderedCanvasZ_ || + !this.renderedCanvasTileRange_.containsTileRange(tileRange)) { + this.renderedCanvasTileRange_ = null; } } + var canvasTileRange, canvasTileRangeWidth, minX, minY; + if (z != this.renderedCanvasZ_ || + goog.isNull(this.renderedCanvasTileRange_)) { + if (goog.isNull(this.canvasSize_)) { + this.canvasSize_ = new ol.Size(canvasWidth, canvasHeight); + } else { + this.canvasSize_.width = canvasWidth; + this.canvasSize_.height = canvasHeight; + } + canvasTileRangeWidth = canvasWidth / tileSize.width; + var canvasTileRangeHeight = canvasHeight / tileSize.height; + minX = tileRange.minX + + Math.floor((canvasTileRangeWidth - tileRange.getWidth()) / 2); + minY = tileRange.minY + + Math.floor((canvasTileRangeHeight - tileRange.getHeight()) / 2); + this.renderedCanvasZ_ = z; + this.renderedCanvasTileRange_ = new ol.TileRange( + minX, minY, + minX + canvasTileRangeWidth - 1, minY + canvasTileRangeHeight - 1); + this.renderedTiles_ = + new Array(canvasTileRangeWidth * canvasTileRangeHeight); + canvasTileRange = this.renderedCanvasTileRange_; + } else { + canvasTileRange = this.renderedCanvasTileRange_; + canvasTileRangeWidth = canvasTileRange.getWidth(); + } + + goog.asserts.assert(!goog.isNull(this.canvasSize_)); + goog.asserts.assert(canvasTileRange.containsTileRange(tileRange)); + /** * @type {Object.>} */ @@ -178,10 +223,10 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = var zs = goog.array.map(goog.object.getKeys(tilesToDrawByZ), Number); goog.array.sort(zs); var opaque = tileSource.getOpaque(); - var origin = tileGrid.getTileCoordExtent( - new ol.TileCoord(z, tileRange.minX, tileRange.maxY)).getTopLeft(); + var origin = tileGrid.getTileCoordExtent(new ol.TileCoord( + z, canvasTileRange.minX, canvasTileRange.maxY)).getTopLeft(); var currentZ, i, index, scale, tileCoordKey, tileExtent, tilesToDraw; - var ix, iy, interimTileExtent, interimTileRange, maxX, maxY, minX, minY; + var ix, iy, interimTileExtent, interimTileRange, maxX, maxY; var height, width; for (i = 0; i < zs.length; ++i) { currentZ = zs[i]; @@ -190,11 +235,12 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = if (currentZ == z) { for (tileCoordKey in tilesToDraw) { tile = tilesToDraw[tileCoordKey]; - index = (tile.tileCoord.y - tileRange.minY) * tileRangeWidth + - (tile.tileCoord.x - tileRange.minX); + index = + (tile.tileCoord.y - canvasTileRange.minY) * canvasTileRangeWidth + + (tile.tileCoord.x - canvasTileRange.minX); if (this.renderedTiles_[index] != tile) { - x = tileSize.width * (tile.tileCoord.x - tileRange.minX); - y = tileSize.height * (tileRange.maxY - tile.tileCoord.y); + x = tileSize.width * (tile.tileCoord.x - canvasTileRange.minX); + y = tileSize.height * (canvasTileRange.maxY - tile.tileCoord.y); tileState = tile.getState(); if (tileState == ol.TileState.EMPTY || !opaque) { context.clearRect(x, y, tileSize.width, tileSize.height); @@ -223,14 +269,15 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = } interimTileRange = tileGrid.getTileRangeForExtentAndZ(tileExtent, z); - minX = Math.max(interimTileRange.minX, tileRange.minX); - maxX = Math.min(interimTileRange.maxX, tileRange.maxX); - minY = Math.max(interimTileRange.minY, tileRange.minY); - maxY = Math.min(interimTileRange.maxY, tileRange.maxY); + minX = Math.max(interimTileRange.minX, canvasTileRange.minX); + maxX = Math.min(interimTileRange.maxX, canvasTileRange.maxX); + minY = Math.max(interimTileRange.minY, canvasTileRange.minY); + maxY = Math.min(interimTileRange.maxY, canvasTileRange.maxY); for (ix = minX; ix <= maxX; ++ix) { for (iy = minY; iy <= maxY; ++iy) { - this.renderedTiles_[(iy - tileRange.minY) * tileRangeWidth + - (ix - tileRange.minX)] = undefined; + index = (iy - canvasTileRange.minY) * canvasTileRangeWidth + + (ix - canvasTileRange.minX); + this.renderedTiles_[index] = undefined; } } } diff --git a/src/ol/tilerange.js b/src/ol/tilerange.js index 76d3d7437c..b428e07c89 100644 --- a/src/ol/tilerange.js +++ b/src/ol/tilerange.js @@ -80,7 +80,7 @@ ol.TileRange.prototype.contains = function(tileCoord) { */ ol.TileRange.prototype.containsTileRange = function(tileRange) { return this.minX <= tileRange.minX && tileRange.maxX <= this.maxX && - this.minY <= tileRange.minY && tileRange.minY <= this.maxY; + this.minY <= tileRange.minY && tileRange.maxY <= this.maxY; };