diff --git a/src/ol/Disposable.js b/src/ol/Disposable.js index d7800fa2b8..da4cb6b60f 100644 --- a/src/ol/Disposable.js +++ b/src/ol/Disposable.js @@ -14,15 +14,15 @@ class Disposable { * @type {boolean} * @private */ - this.disposed_ = false; + this.disposed = false; } /** * Clean up. */ dispose() { - if (!this.disposed_) { - this.disposed_ = true; + if (!this.disposed) { + this.disposed = true; this.disposeInternal(); } } diff --git a/src/ol/renderer/canvas/VectorTileLayer.js b/src/ol/renderer/canvas/VectorTileLayer.js index 5331a24fd7..4390579207 100644 --- a/src/ol/renderer/canvas/VectorTileLayer.js +++ b/src/ol/renderer/canvas/VectorTileLayer.js @@ -122,6 +122,12 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { */ this.renderedLayerRevision_; + /** + * @private + * @type {Object} + */ + this.tilesToPrepare_ = null; + /** * @private * @type {import("../../transform.js").Transform} @@ -151,17 +157,23 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { if (tile.getState() === TileState.IDLE) { const key = listen(tile, EventType.CHANGE, function() { if (tile.sourceTilesLoaded) { - this.createExecutorGroup_(tile, pixelRatio, projection); + this.updateExecutorGroup_(tile, pixelRatio, projection); + if (!this.tilesToPrepare_) { + this.tilesToPrepare_ = {}; + tile.setState(TileState.LOADED); + } else { + const tileId = getUid(tile); + if (!(tileId in this.tilesToPrepare_)) { + this.tilesToPrepare_[tileId] = [tile, pixelRatio, projection]; + } + } unlistenByKey(key); - tile.setState(TileState.LOADED); } }.bind(this)); } if (tile.getState() === TileState.LOADED) { - this.createExecutorGroup_(tile, pixelRatio, projection); - if (this.context) { - this.renderTileImage_(tile, pixelRatio, projection); - } + this.updateExecutorGroup_(tile, pixelRatio, projection); + this.renderTileImage_(tile, pixelRatio, projection); } return tile; } @@ -193,7 +205,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { * @param {import("../../proj/Projection.js").default} projection Projection. * @private */ - createExecutorGroup_(tile, pixelRatio, projection) { + updateExecutorGroup_(tile, pixelRatio, projection) { const layer = /** @type {import("../../layer/Vector.js").default} */ (this.getLayer()); const revision = layer.getRevision(); const renderOrder = /** @type {import("../../render.js").OrderFunction} */ (layer.getRenderOrder()) || null; @@ -413,7 +425,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { this.declutterTree_.clear(); } const viewHints = frameState.viewHints; - const snapToPixel = !(viewHints[ViewHint.ANIMATING] || viewHints[ViewHint.INTERACTING]); + const hifi = !(viewHints[ViewHint.ANIMATING] || viewHints[ViewHint.INTERACTING]); const tiles = this.renderedTiles; const tileGrid = source.getTileGridForProjection(frameState.viewState.projection); const clips = []; @@ -460,14 +472,14 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { context.clip(); } } - executorGroup.execute(context, transform, rotation, {}, snapToPixel, replayTypes, declutterReplays); + executorGroup.execute(context, transform, rotation, {}, hifi, replayTypes, declutterReplays); context.restore(); clips.push(currentClip); zs.push(currentZ); } } if (declutterReplays) { - replayDeclutter(declutterReplays, context, rotation, snapToPixel); + replayDeclutter(declutterReplays, context, rotation, hifi); } const opacity = layerState.opacity; @@ -475,6 +487,27 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { canvas.style.opacity = opacity; } + if (this.tilesToPrepare_) { + for (const key in this.tilesToPrepare_) { + if (!hifi || Date.now() - frameState.time >= 16) { + break; + } + const args = this.tilesToPrepare_[key]; + delete this.tilesToPrepare_[key]; + const tile = args[0]; + if (!tile.disposed) { + frameState.animate = true; + this.renderTileImage_.apply(this, args); + tile.setState(TileState.LOADED); + } + } + if (Object.keys(this.tilesToPrepare_).length > 0) { + frameState.animate = true; + } else { + this.tilesToPrepare_ = null; + } + } + return this.container_; } diff --git a/test/spec/ol/disposable.test.js b/test/spec/ol/disposable.test.js index 21907b9bbd..168446f186 100644 --- a/test/spec/ol/disposable.test.js +++ b/test/spec/ol/disposable.test.js @@ -12,17 +12,17 @@ describe('ol.Disposable', function() { }); - describe('#disposed_', function() { + describe('#disposed', function() { it('is initially false', function() { const disposable = new Disposable(); - expect(disposable.disposed_).to.be(false); + expect(disposable.disposed).to.be(false); }); it('is true after a call to dispose', function() { const disposable = new Disposable(); disposable.dispose(); - expect(disposable.disposed_).to.be(true); + expect(disposable.disposed).to.be(true); }); }); diff --git a/test/spec/ol/vectorimagetile.test.js b/test/spec/ol/vectorimagetile.test.js index 63a1073b4b..b1b093a68b 100644 --- a/test/spec/ol/vectorimagetile.test.js +++ b/test/spec/ol/vectorimagetile.test.js @@ -30,7 +30,7 @@ describe('ol.VectorImageTile', function() { }); }); - it('sets LOADED state when previously failed source tiles are loaded', function(done) { + it('sets sourceTilesLoaded when previously failed source tiles are loaded', function(done) { const format = new GeoJSON(); const url = 'spec/ol/data/unavailable.json'; let sourceTile; @@ -47,7 +47,11 @@ describe('ol.VectorImageTile', function() { let calls = 0; listen(tile, 'change', function(e) { ++calls; - expect(tile.getState()).to.be(calls == 2 ? TileState.LOADED : TileState.ERROR); + if (calls === 1) { + expect(tile.sourceTilesLoaded).to.be(false); + } else if (calls === 2) { + expect(tile.sourceTilesLoaded).to.be(true); + } if (calls == 2) { done(); } else { @@ -131,7 +135,7 @@ describe('ol.VectorImageTile', function() { expect(tile.getState()).to.be(TileState.ABORT); }); - it('#dispose() when loaded', function(done) { + it('#dispose() when source tiles are loaded', function(done) { const format = new GeoJSON(); const url = 'spec/ol/data/point.json'; const tile = new VectorImageTile([0, 0, 0], 0, url, format, @@ -142,7 +146,8 @@ describe('ol.VectorImageTile', function() { tile.load(); listenOnce(tile, 'change', function() { - expect(tile.getState()).to.be(TileState.LOADED); + expect(tile.getState()).to.be(TileState.LOADING); + expect(tile.sourceTilesLoaded).to.be.ok(); expect(tile.loadListenerKeys_.length).to.be(0); expect(tile.tileKeys.length).to.be(4); tile.dispose();