From 76726a3a6f87d366f39f2e299566e90a84234e2b Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Sat, 16 Sep 2017 15:53:29 -0600 Subject: [PATCH] Render tiles with an opacity transition --- src/ol/renderer/canvas/tilelayer.js | 18 ++++++++++--- src/ol/tile.js | 42 +++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/ol/renderer/canvas/tilelayer.js b/src/ol/renderer/canvas/tilelayer.js index ab2d0a480b..87537ffc41 100644 --- a/src/ol/renderer/canvas/tilelayer.js +++ b/src/ol/renderer/canvas/tilelayer.js @@ -183,7 +183,7 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame = function(frameState, layer if (this.isDrawableTile_(tile)) { if (tile.getState() == ol.TileState.LOADED) { tilesToDrawByZ[z][tile.tileCoord.toString()] = tile; - if (!newTiles && this.renderedTiles.indexOf(tile) == -1) { + if (!newTiles && (this.renderedTiles.indexOf(tile) === -1 || tile.getAlpha(ol.getUid(this), frameState.time) !== 1)) { newTiles = true; } } @@ -225,7 +225,6 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame = function(frameState, layer canvas.width = width; canvas.height = height; } else { - context.clearRect(0, 0, width, height); oversampling = this.oversampling_; } } @@ -295,13 +294,26 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame = function(frameState, layer * @param {number} gutter Tile gutter. */ ol.renderer.canvas.TileLayer.prototype.drawTileImage = function(tile, frameState, layerState, x, y, w, h, gutter) { - if (!this.getLayer().getSource().getOpaque(frameState.viewState.projection)) { + var alpha = tile.getAlpha(ol.getUid(this), frameState.time); + if (alpha === 1 && !this.getLayer().getSource().getOpaque(frameState.viewState.projection)) { this.context.clearRect(x, y, w, h); } var image = tile.getImage(this.getLayer()); if (image) { + var alphaChanged = alpha !== this.context.globalAlpha; + if (alphaChanged) { + this.context.save(); + this.context.globalAlpha = alpha; + } this.context.drawImage(image, gutter, gutter, image.width - 2 * gutter, image.height - 2 * gutter, x, y, w, h); + + if (alphaChanged) { + this.context.restore(); + } + if (alpha !== 1) { + frameState.animate = true; + } } }; diff --git a/src/ol/tile.js b/src/ol/tile.js index 9a1bfe7e84..e5676e9e4b 100644 --- a/src/ol/tile.js +++ b/src/ol/tile.js @@ -1,6 +1,7 @@ goog.provide('ol.Tile'); goog.require('ol'); +goog.require('ol.easing'); goog.require('ol.TileState'); goog.require('ol.events.EventTarget'); goog.require('ol.events.EventType'); @@ -47,6 +48,24 @@ ol.Tile = function(tileCoord, state) { */ this.key = ''; + /** + * The timing function to apply to any opacity transition. + * @type {function(number):number} + */ + this.transitionEasing_ = ol.easing.linear; + + /** + * The duration for the opacity transition. + * @type {number} + */ + this.transitionDuration_ = 250; + + /** + * Lookup of start times for rendering transitions. + * @type {Object.} + */ + this.transitionStarts_ = {}; + }; ol.inherits(ol.Tile, ol.events.EventTarget); @@ -161,3 +180,26 @@ ol.Tile.prototype.setState = function(state) { * @api */ ol.Tile.prototype.load = function() {}; + +/** + * Get the alpha value for rendering. + * @param {number} id An id for the renderer. + * @param {number} time The render frame time. + * @return {number} A number between 0 and 1. + */ +ol.Tile.prototype.getAlpha = function(id, time) { + if (!this.transitionEasing_) { + return 1; + } + + var start = this.transitionStarts_[id]; + if (!start) { + start = time; + this.transitionStarts_[id] = start; + } + var delta = Date.now() - start + (1000 / 60); // avoid rendering at 0 + if (delta >= this.transitionDuration_) { + return 1; + } + return this.transitionEasing_(delta / this.transitionDuration_); +};