From 7739239e898f9a22da88979c9fe1a9ab7747728b Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Sun, 9 Jul 2017 14:08:08 +0200 Subject: [PATCH] Make VectorTile source work with multiple layers --- src/ol/renderer/canvas/tilelayer.js | 2 +- src/ol/renderer/canvas/vectortilelayer.js | 15 +++---- src/ol/vectorimagetile.js | 44 +++++++++++-------- src/ol/vectortile.js | 10 +++-- .../renderer/canvas/vectortilelayer.test.js | 26 ++++++++++- 5 files changed, 64 insertions(+), 33 deletions(-) diff --git a/src/ol/renderer/canvas/tilelayer.js b/src/ol/renderer/canvas/tilelayer.js index 2fb975e72c..b20a916b41 100644 --- a/src/ol/renderer/canvas/tilelayer.js +++ b/src/ol/renderer/canvas/tilelayer.js @@ -274,7 +274,7 @@ ol.renderer.canvas.TileLayer.prototype.drawTileImage = function(tile, frameState if (!this.getLayer().getSource().getOpaque(frameState.viewState.projection)) { this.context.clearRect(x, y, w, h); } - var image = tile.getImage(); + var image = tile.getImage(this.getLayer()); if (image) { this.context.drawImage(image, gutter, gutter, image.width - 2 * gutter, image.height - 2 * gutter, x, y, w, h); diff --git a/src/ol/renderer/canvas/vectortilelayer.js b/src/ol/renderer/canvas/vectortilelayer.js index 6b1570b11c..78cc7f3e23 100644 --- a/src/ol/renderer/canvas/vectortilelayer.js +++ b/src/ol/renderer/canvas/vectortilelayer.js @@ -111,7 +111,7 @@ ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup_ = function( var renderOrder = /** @type {ol.RenderOrderFunction} */ (layer.getRenderOrder()) || null; - var replayState = tile.getReplayState(); + var replayState = tile.getReplayState(layer); if (!replayState.dirty && replayState.renderedRevision == revision && replayState.renderedRenderOrder == renderOrder) { return; @@ -119,7 +119,6 @@ ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup_ = function( for (var t = 0, tt = tile.tileKeys.length; t < tt; ++t) { var sourceTile = tile.getTile(tile.tileKeys[t]); - sourceTile.replayGroup = null; replayState.dirty = false; var source = /** @type {ol.source.VectorTile} */ (layer.getSource()); @@ -195,7 +194,7 @@ ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup_ = function( renderFeature.call(this, feature); } replayGroup.finish(); - sourceTile.setReplayGroup(tile.tileCoord.toString(), replayGroup); + sourceTile.setReplayGroup(layer, tile.tileCoord.toString(), replayGroup); } replayState.renderedRevision = revision; replayState.renderedRenderOrder = renderOrder; @@ -260,7 +259,7 @@ ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate = functi } else { tileSpaceCoordinate = coordinate; } - replayGroup = sourceTile.getReplayGroup(tile.tileCoord.toString()); + replayGroup = sourceTile.getReplayGroup(layer, tile.tileCoord.toString()); found = found || replayGroup.forEachFeatureAtCoordinate( tileSpaceCoordinate, resolution, rotation, hitTolerance, {}, /** @@ -359,7 +358,7 @@ ol.renderer.canvas.VectorTileLayer.prototype.postCompose = function(context, fra var sourceResolution = sourceTileGrid.getResolution(currentZ); var transform = this.getReplayTransform_(sourceTile, frameState); ol.transform.translate(transform, worldOffset * tilePixelRatio / sourceResolution, 0); - var replayGroup = sourceTile.getReplayGroup(tileCoord.toString()); + var replayGroup = sourceTile.getReplayGroup(layer, tileCoord.toString()); var currentClip = replayGroup.getClipCoords(transform); context.save(); context.globalAlpha = layerState.opacity; @@ -431,7 +430,7 @@ ol.renderer.canvas.VectorTileLayer.prototype.renderFeature = function(feature, s ol.renderer.canvas.VectorTileLayer.prototype.renderTileImage_ = function( tile, frameState, layerState) { var layer = this.getLayer(); - var replayState = tile.getReplayState(); + var replayState = tile.getReplayState(layer); var revision = layer.getRevision(); var replays = ol.renderer.canvas.VectorTileLayer.IMAGE_REPLAYS[layer.getRenderMode()]; if (replays && replayState.renderedTileRevision !== revision) { @@ -444,7 +443,7 @@ ol.renderer.canvas.VectorTileLayer.prototype.renderTileImage_ = function( var tileGrid = source.getTileGridForProjection(frameState.viewState.projection); var resolution = tileGrid.getResolution(z); var tilePixelRatio = source.getTilePixelRatio(); - var context = tile.getContext(); + var context = tile.getContext(layer); var size = source.getTilePixelSize(z, pixelRatio, frameState.viewState.projection); context.canvas.width = size[0]; context.canvas.height = size[1]; @@ -466,7 +465,7 @@ ol.renderer.canvas.VectorTileLayer.prototype.renderTileImage_ = function( ol.transform.scale(transform, pixelScale, -pixelScale); ol.transform.translate(transform, -tileExtent[0], -tileExtent[3]); } - var replayGroup = sourceTile.getReplayGroup(tile.tileCoord.toString()); + var replayGroup = sourceTile.getReplayGroup(layer, tile.tileCoord.toString()); replayGroup.replay(context, pixelRatio, transform, 0, {}, replays); } } diff --git a/src/ol/vectorimagetile.js b/src/ol/vectorimagetile.js index 1ad0aeecac..a0f12c4a8c 100644 --- a/src/ol/vectorimagetile.js +++ b/src/ol/vectorimagetile.js @@ -40,9 +40,9 @@ ol.VectorImageTile = function(tileCoord, state, src, format, tileLoadFunction, /** * @private - * @type {CanvasRenderingContext2D} + * @type {Object.} */ - this.context_ = null; + this.context_ = {}; /** * @private @@ -52,14 +52,9 @@ ol.VectorImageTile = function(tileCoord, state, src, format, tileLoadFunction, /** * @private - * @type {ol.TileReplayState} + * @type {Object.} */ - this.replayState_ = { - dirty: false, - renderedRenderOrder: null, - renderedRevision: -1, - renderedTileRevision: -1 - }; + this.replayState_ = {}; /** * @private @@ -155,31 +150,44 @@ ol.VectorImageTile.prototype.disposeInternal = function() { /** + * @param {ol.layer.Layer} layer Layer. * @return {CanvasRenderingContext2D} The rendering context. */ -ol.VectorImageTile.prototype.getContext = function() { - if (!this.context_) { - this.context_ = ol.dom.createCanvasContext2D(); +ol.VectorImageTile.prototype.getContext = function(layer) { + var key = ol.getUid(layer).toString(); + if (!(key in this.context_)) { + this.context_[key] = ol.dom.createCanvasContext2D(); } - return this.context_; + return this.context_[key]; }; /** * Get the Canvas for this tile. + * @param {ol.layer.Layer} layer Layer. * @return {HTMLCanvasElement} Canvas. */ -ol.VectorImageTile.prototype.getImage = function() { - return this.replayState_.renderedTileRevision == -1 ? - null : this.context_.canvas; +ol.VectorImageTile.prototype.getImage = function(layer) { + return this.getReplayState(layer).renderedTileRevision == -1 ? + null : this.getContext(layer).canvas; }; /** + * @param {ol.layer.Layer} layer Layer. * @return {ol.TileReplayState} The replay state. */ -ol.VectorImageTile.prototype.getReplayState = function() { - return this.replayState_; +ol.VectorImageTile.prototype.getReplayState = function(layer) { + var key = ol.getUid(layer).toString(); + if (!(key in this.replayState_)) { + this.replayState_[key] = { + dirty: false, + renderedRenderOrder: null, + renderedRevision: -1, + renderedTileRevision: -1 + }; + } + return this.replayState_[key]; }; diff --git a/src/ol/vectortile.js b/src/ol/vectortile.js index 9976b567ba..f3335f362c 100644 --- a/src/ol/vectortile.js +++ b/src/ol/vectortile.js @@ -122,11 +122,12 @@ ol.VectorTile.prototype.getProjection = function() { /** + * @param {ol.layer.Layer} layer Layer. * @param {string} key Key. * @return {ol.render.ReplayGroup} Replay group. */ -ol.VectorTile.prototype.getReplayGroup = function(key) { - return this.replayGroups_[key]; +ol.VectorTile.prototype.getReplayGroup = function(layer, key) { + return this.replayGroups_[ol.getUid(layer) + ',' + key]; }; @@ -182,11 +183,12 @@ ol.VectorTile.prototype.setProjection = function(projection) { /** + * @param {ol.layer.Layer} layer Layer. * @param {string} key Key. * @param {ol.render.ReplayGroup} replayGroup Replay group. */ -ol.VectorTile.prototype.setReplayGroup = function(key, replayGroup) { - this.replayGroups_[key] = replayGroup; +ol.VectorTile.prototype.setReplayGroup = function(layer, key, replayGroup) { + this.replayGroups_[ol.getUid(layer) + ',' + key] = replayGroup; }; diff --git a/test/spec/ol/renderer/canvas/vectortilelayer.test.js b/test/spec/ol/renderer/canvas/vectortilelayer.test.js index 7ad7802b94..0b9664f200 100644 --- a/test/spec/ol/renderer/canvas/vectortilelayer.test.js +++ b/test/spec/ol/renderer/canvas/vectortilelayer.test.js @@ -21,7 +21,7 @@ describe('ol.renderer.canvas.VectorTileLayer', function() { describe('constructor', function() { - var map, layer, feature1, feature2, target, tileCallback; + var map, layer, source, feature1, feature2, target, tileCallback; beforeEach(function() { tileCallback = function() {}; @@ -57,7 +57,7 @@ describe('ol.renderer.canvas.VectorTileLayer', function() { tileCallback(this); }; ol.inherits(TileClass, ol.VectorTile); - var source = new ol.source.VectorTile({ + source = new ol.source.VectorTile({ format: new ol.format.MVT(), tileClass: TileClass, tileGrid: ol.tilegrid.createXYZ() @@ -152,6 +152,28 @@ describe('ol.renderer.canvas.VectorTileLayer', function() { expect(feature1.getGeometry().getCoordinates()).to.eql([1, -1]); }); + it('works for multiple layers that use the same source', function() { + var layer2 = new ol.layer.VectorTile({ + source: source, + style: new ol.style.Style({ + text: new ol.style.Text({ + text: 'layer2' + }) + }) + }); + map.addLayer(layer2); + + var spy1 = sinon.spy(ol.VectorTile.prototype, + 'getReplayGroup'); + var spy2 = sinon.spy(ol.VectorTile.prototype, + 'setReplayGroup'); + map.renderSync(); + expect(spy1.callCount).to.be(4); + expect(spy2.callCount).to.be(2); + spy1.restore(); + spy2.restore(); + }); + }); describe('#prepareFrame', function() {