UNPKG

openlayers

Version:

Build tools and sources for developing OpenLayers based mapping applications

279 lines (235 loc) 8.56 kB
// FIXME find correct globalCompositeOperation goog.provide('ol.renderer.canvas.TileLayer'); goog.require('ol'); goog.require('ol.transform'); goog.require('ol.TileRange'); goog.require('ol.Tile'); goog.require('ol.array'); goog.require('ol.dom'); goog.require('ol.extent'); goog.require('ol.renderer.canvas.IntermediateCanvas'); /** * @constructor * @extends {ol.renderer.canvas.IntermediateCanvas} * @param {ol.layer.Tile|ol.layer.VectorTile} tileLayer Tile layer. */ ol.renderer.canvas.TileLayer = function(tileLayer) { ol.renderer.canvas.IntermediateCanvas.call(this, tileLayer); /** * @protected * @type {CanvasRenderingContext2D} */ this.context = ol.dom.createCanvasContext2D(); /** * @private * @type {ol.Extent} */ this.renderedExtent_ = null; /** * @private * @type {number} */ this.renderedRevision_; /** * @protected * @type {!Array.<ol.Tile>} */ this.renderedTiles = []; /** * @protected * @type {ol.Extent} */ this.tmpExtent = ol.extent.createEmpty(); /** * @private * @type {ol.TileCoord} */ this.tmpTileCoord_ = [0, 0, 0]; /** * @private * @type {ol.TileRange} */ this.tmpTileRange_ = new ol.TileRange(0, 0, 0, 0); /** * @private * @type {ol.Transform} */ this.imageTransform_ = ol.transform.create(); /** * @protected * @type {number} */ this.zDirection = 0; }; ol.inherits(ol.renderer.canvas.TileLayer, ol.renderer.canvas.IntermediateCanvas); /** * @inheritDoc */ ol.renderer.canvas.TileLayer.prototype.prepareFrame = function(frameState, layerState) { var pixelRatio = frameState.pixelRatio; var size = frameState.size; var viewState = frameState.viewState; var projection = viewState.projection; var viewResolution = viewState.resolution; var viewCenter = viewState.center; var tileLayer = this.getLayer(); var tileSource = /** @type {ol.source.Tile} */ (tileLayer.getSource()); var sourceRevision = tileSource.getRevision(); var tileGrid = tileSource.getTileGridForProjection(projection); var z = tileGrid.getZForResolution(viewResolution, this.zDirection); var tileResolution = tileGrid.getResolution(z); var extent = frameState.extent; if (layerState.extent !== undefined) { extent = ol.extent.getIntersection(extent, layerState.extent); } if (ol.extent.isEmpty(extent)) { // Return false to prevent the rendering of the layer. return false; } var tileRange = tileGrid.getTileRangeForExtentAndResolution( extent, tileResolution); var imageExtent = tileGrid.getTileRangeExtent(z, tileRange); var tilePixelRatio = tileSource.getTilePixelRatio(pixelRatio); /** * @type {Object.<number, Object.<string, ol.Tile>>} */ var tilesToDrawByZ = {}; tilesToDrawByZ[z] = {}; var findLoadedTiles = this.createLoadedTileFinder( tileSource, projection, tilesToDrawByZ); var useInterimTilesOnError = tileLayer.getUseInterimTilesOnError(); var tmpExtent = this.tmpExtent; var tmpTileRange = this.tmpTileRange_; var newTiles = false; var tile, x, y; for (x = tileRange.minX; x <= tileRange.maxX; ++x) { for (y = tileRange.minY; y <= tileRange.maxY; ++y) { tile = tileSource.getTile(z, x, y, pixelRatio, projection); var tileState = tile.getState(); var drawable = tileState == ol.Tile.State.LOADED || tileState == ol.Tile.State.EMPTY || tileState == ol.Tile.State.ERROR && !useInterimTilesOnError; if (!drawable) { tile = tile.getInterimTile(); } else { if (tileState == ol.Tile.State.LOADED) { tilesToDrawByZ[z][tile.tileCoord.toString()] = tile; if (!newTiles && this.renderedTiles.indexOf(tile) == -1) { newTiles = true; } } continue; } var fullyLoaded = tileGrid.forEachTileCoordParentTileRange( tile.tileCoord, findLoadedTiles, null, tmpTileRange, tmpExtent); if (!fullyLoaded) { var childTileRange = tileGrid.getTileCoordChildTileRange( tile.tileCoord, tmpTileRange, tmpExtent); if (childTileRange) { findLoadedTiles(z + 1, childTileRange); } } } } var hints = frameState.viewHints; if (!(this.renderedResolution && Date.now() - frameState.time > 16 && (hints[ol.View.Hint.ANIMATING] || hints[ol.View.Hint.INTERACTING])) && (newTiles || !(this.renderedExtent_ && ol.extent.equals(this.renderedExtent_, imageExtent)) || this.renderedRevision_ != sourceRevision)) { var tilePixelSize = tileSource.getTilePixelSize(z, pixelRatio, projection); var width = tileRange.getWidth() * tilePixelSize[0]; var height = tileRange.getHeight() * tilePixelSize[0]; var context = this.context; var canvas = context.canvas; var opaque = tileSource.getOpaque(projection); if (canvas.width != width || canvas.height != height) { canvas.width = width; canvas.height = height; } else { context.clearRect(0, 0, width, height); } this.renderedTiles.length = 0; /** @type {Array.<number>} */ var zs = Object.keys(tilesToDrawByZ).map(Number); zs.sort(ol.array.numberSafeCompareFunction); var currentResolution, currentScale, currentTilePixelSize, currentZ, i, ii; var tileExtent, tileGutter, tilesToDraw, w, h; for (i = 0, ii = zs.length; i < ii; ++i) { currentZ = zs[i]; currentTilePixelSize = tileSource.getTilePixelSize(currentZ, pixelRatio, projection); currentResolution = tileGrid.getResolution(currentZ); currentScale = currentResolution / tileResolution; tileGutter = tilePixelRatio * tileSource.getGutter(projection); tilesToDraw = tilesToDrawByZ[currentZ]; for (var tileCoordKey in tilesToDraw) { tile = tilesToDraw[tileCoordKey]; tileExtent = tileGrid.getTileCoordExtent(tile.getTileCoord(), tmpExtent); x = (tileExtent[0] - imageExtent[0]) / tileResolution * tilePixelRatio; y = (imageExtent[3] - tileExtent[3]) / tileResolution * tilePixelRatio; w = currentTilePixelSize[0] * currentScale; h = currentTilePixelSize[1] * currentScale; if (!opaque) { context.clearRect(x, y, w, h); } this.drawTileImage(tile, frameState, layerState, x, y, w, h, tileGutter); this.renderedTiles.push(tile); } } this.renderedRevision_ = sourceRevision; this.renderedResolution = tileResolution; this.renderedExtent_ = imageExtent; } var scale = pixelRatio / tilePixelRatio * this.renderedResolution / viewResolution; var transform = ol.transform.compose(this.imageTransform_, pixelRatio * size[0] / 2, pixelRatio * size[1] / 2, scale, scale, 0, tilePixelRatio * (this.renderedExtent_[0] - viewCenter[0]) / this.renderedResolution, tilePixelRatio * (viewCenter[1] - this.renderedExtent_[3]) / this.renderedResolution); ol.transform.compose(this.coordinateToCanvasPixelTransform, pixelRatio * size[0] / 2 - transform[4], pixelRatio * size[1] / 2 - transform[5], pixelRatio / viewResolution, -pixelRatio / viewResolution, 0, -viewCenter[0], -viewCenter[1]); this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange); this.manageTilePyramid(frameState, tileSource, tileGrid, pixelRatio, projection, extent, z, tileLayer.getPreload()); this.scheduleExpireCache(frameState, tileSource); this.updateLogos(frameState, tileSource); return this.renderedTiles.length > 0; }; /** * @param {ol.Tile} tile Tile. * @param {olx.FrameState} frameState Frame state. * @param {ol.LayerState} layerState Layer state. * @param {number} x Left of the tile. * @param {number} y Top of the tile. * @param {number} w Width of the tile. * @param {number} h Height of the tile. * @param {number} gutter Tile gutter. */ ol.renderer.canvas.TileLayer.prototype.drawTileImage = function(tile, frameState, layerState, x, y, w, h, gutter) { var image = tile.getImage(); if (image) { this.context.drawImage(image, gutter, gutter, image.width - 2 * gutter, image.height - 2 * gutter, x, y, w, h); } }; /** * @inheritDoc */ ol.renderer.canvas.TileLayer.prototype.getImage = function() { return this.context.canvas; }; /** * @function * @return {ol.layer.Tile|ol.layer.VectorTile} */ ol.renderer.canvas.TileLayer.prototype.getLayer; /** * @inheritDoc */ ol.renderer.canvas.TileLayer.prototype.getImageTransform = function() { return this.imageTransform_; };