From 174dea32327da6b2228fcd094f0a15833b9cf140 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Sat, 7 Dec 2019 13:58:58 +0100 Subject: [PATCH] Fix interim tile handing for vector tiles --- src/ol/renderer/canvas/VectorTileLayer.js | 7 ++- src/ol/source/VectorTile.js | 31 +++++----- .../renderer/canvas/vectortilelayer.test.js | 3 +- test/spec/ol/source/vectortile.test.js | 59 +++++++++++++++++++ test/spec/ol/vectorrendertile.test.js | 2 +- 5 files changed, 80 insertions(+), 22 deletions(-) diff --git a/src/ol/renderer/canvas/VectorTileLayer.js b/src/ol/renderer/canvas/VectorTileLayer.js index bcb25d234d..785f0b3d3d 100644 --- a/src/ol/renderer/canvas/VectorTileLayer.js +++ b/src/ol/renderer/canvas/VectorTileLayer.js @@ -139,11 +139,12 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { * @inheritDoc */ getTile(z, x, y, frameState) { - const tile = /** @type {import("../../VectorRenderTile.js").default} */ (super.getTile(z, x, y, frameState)); const pixelRatio = frameState.pixelRatio; const viewState = frameState.viewState; const resolution = viewState.resolution; const projection = viewState.projection; + const layer = this.getLayer(); + const tile = layer.getSource().getTile(z, x, y, pixelRatio, projection); if (tile.getState() < TileState.LOADED) { tile.wantedResolution = resolution; const tileUid = getUid(tile); @@ -158,11 +159,11 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { tile.wantedResolution = resolution; } const render = this.prepareTile(tile, pixelRatio, projection, false); - if (render && this.getLayer().getRenderMode() !== VectorTileRenderType.VECTOR) { + if (render && layer.getRenderMode() !== VectorTileRenderType.VECTOR) { this.renderTileImage_(tile, frameState); } } - return tile; + return super.getTile(z, x, y, frameState); } /** diff --git a/src/ol/source/VectorTile.js b/src/ol/source/VectorTile.js index 8c34a22ff9..8fb5496cce 100644 --- a/src/ol/source/VectorTile.js +++ b/src/ol/source/VectorTile.js @@ -7,7 +7,7 @@ import VectorRenderTile from '../VectorRenderTile.js'; import Tile from '../VectorTile.js'; import {toSize} from '../size.js'; import UrlTile from './UrlTile.js'; -import {getKeyZXY, getKey} from '../tilecoord.js'; +import {getKeyZXY} from '../tilecoord.js'; import {createXYZ, extentFromProjection, createForProjection} from '../tilegrid.js'; import {buffer as bufferExtent, getIntersection, intersects} from '../extent.js'; import EventType from '../events/EventType.js'; @@ -131,7 +131,7 @@ class VectorTile extends UrlTile { * @private * @type {Object} */ - this.sourceTileByCoordKey_ = {}; + this.sourceTileByKey_ = {}; /** * @private @@ -172,7 +172,7 @@ class VectorTile extends UrlTile { */ clear() { this.tileCache.clear(); - this.sourceTileByCoordKey_ = {}; + this.sourceTileByKey_ = {}; this.sourceTilesByTileKey_ = {}; } @@ -211,24 +211,23 @@ class VectorTile extends UrlTile { --loadedZ; covered = true; sourceTileGrid.forEachTileCoord(extent, loadedZ, function(sourceTileCoord) { - const coordKey = getKey(sourceTileCoord); + const tileUrl = this.tileUrlFunction(sourceTileCoord, pixelRatio, projection); let sourceTile; - if (coordKey in this.sourceTileByCoordKey_) { - sourceTile = this.sourceTileByCoordKey_[coordKey]; - const state = sourceTile.getState(); - if (state === TileState.LOADED || state === TileState.ERROR || state === TileState.EMPTY) { - sourceTiles.push(sourceTile); - return; - } - } else if (loadedZ === sourceZ) { - const tileUrl = this.tileUrlFunction(sourceTileCoord, pixelRatio, projection); - if (tileUrl !== undefined) { + if (tileUrl !== undefined) { + if (tileUrl in this.sourceTileByKey_) { + sourceTile = this.sourceTileByKey_[tileUrl]; + const state = sourceTile.getState(); + if (state === TileState.LOADED || state === TileState.ERROR || state === TileState.EMPTY) { + sourceTiles.push(sourceTile); + return; + } + } else if (loadedZ === sourceZ) { sourceTile = new this.tileClass(sourceTileCoord, TileState.IDLE, tileUrl, this.format_, this.tileLoadFunction); sourceTile.extent = sourceTileGrid.getTileCoordExtent(sourceTileCoord); sourceTile.projection = projection; sourceTile.resolution = sourceTileGrid.getResolution(sourceTileCoord[0]); - this.sourceTileByCoordKey_[coordKey] = sourceTile; + this.sourceTileByKey_[tileUrl] = sourceTile; sourceTile.addEventListener(EventType.CHANGE, this.handleTileChange.bind(this)); sourceTile.load(); } @@ -307,7 +306,7 @@ class VectorTile extends UrlTile { sourceTile.consumers--; if (sourceTile.consumers === 0) { sourceTile.dispose(); - delete this.sourceTileByCoordKey_[getKey(sourceTile.tileCoord)]; + delete this.sourceTileByKey_[sourceTile.getKey()]; } } } diff --git a/test/spec/ol/renderer/canvas/vectortilelayer.test.js b/test/spec/ol/renderer/canvas/vectortilelayer.test.js index 72475e4db9..eb3193223b 100644 --- a/test/spec/ol/renderer/canvas/vectortilelayer.test.js +++ b/test/spec/ol/renderer/canvas/vectortilelayer.test.js @@ -9,7 +9,6 @@ import {getCenter} from '../../../../../src/ol/extent.js'; import MVT from '../../../../../src/ol/format/MVT.js'; import Point from '../../../../../src/ol/geom/Point.js'; import VectorTileLayer from '../../../../../src/ol/layer/VectorTile.js'; -import {getKey} from '../../../../../src/ol/tilecoord.js'; import {get as getProjection} from '../../../../../src/ol/proj.js'; import {checkedFonts} from '../../../../../src/ol/render/canvas.js'; import RenderFeature from '../../../../../src/ol/render/Feature.js'; @@ -317,7 +316,7 @@ describe('ol.renderer.canvas.VectorTileLayer', function() { tileClass: TileClass, tileGrid: createXYZ() }); - source.sourceTileByCoordKey_[getKey(sourceTile.tileCoord)] = sourceTile; + source.sourceTileByKey_[sourceTile.getKey()] = sourceTile; source.sourceTilesByTileKey_[sourceTile.getKey()] = [sourceTile]; executorGroup = {}; source.getTile = function() { diff --git a/test/spec/ol/source/vectortile.test.js b/test/spec/ol/source/vectortile.test.js index 5a6d519753..f5e6883baf 100644 --- a/test/spec/ol/source/vectortile.test.js +++ b/test/spec/ol/source/vectortile.test.js @@ -11,6 +11,8 @@ import {createXYZ} from '../../../../src/ol/tilegrid.js'; import TileGrid from '../../../../src/ol/tilegrid/TileGrid.js'; import {listen, unlistenByKey} from '../../../../src/ol/events.js'; import TileState from '../../../../src/ol/TileState.js'; +import {getCenter} from '../../../../src/ol/extent.js'; +import {unByKey} from '../../../../src/ol/Observable.js'; describe('ol.source.VectorTile', function() { @@ -295,4 +297,61 @@ describe('ol.source.VectorTile', function() { }); + describe('interim tile handling', function() { + + let map, source, target; + + beforeEach(function() { + target = document.createElement('div'); + target.style.width = '100px'; + target.style.height = '100px'; + document.body.appendChild(target); + const extent = [1824704.739223726, 6141868.096770482, 1827150.7241288517, 6144314.081675608]; + source = new VectorTileSource({ + format: new MVT(), + url: 'spec/ol/data/14-8938-5680.vector.pbf', + minZoom: 14, + maxZoom: 14 + }); + map = new Map({ + pixelRatio: 1, + target: target, + layers: [ + new VectorTileLayer({ + extent: extent, + source: source + }) + ], + view: new View({ + center: getCenter(extent), + zoom: 15 + }) + }); + }); + + afterEach(function() { + map.setTarget(null); + document.body.removeChild(target); + }); + + it('re-renders when source changes', function(done) { + map.once('rendercomplete', function() { + const key = map.on('rendercomplete', function() { + const tile = source.getTile(14, 8938, 5680, 1, map.getView().getProjection()); + expect(tile.getKey()).to.be('spec/ol/data/14-8938-5680.vector.pbf?new/14,8938,5680'); + expect(tile.interimTile).to.be.a(VectorRenderTile); + expect(tile.interimTile.getKey()).to.be('spec/ol/data/14-8938-5680.vector.pbf/14,8938,5680'); + const sourceTiles = source.getSourceTiles(1, map.getView().getProjection(), tile); + if (sourceTiles) { + expect(sourceTiles[0].getKey()).to.be('spec/ol/data/14-8938-5680.vector.pbf?new'); + unByKey(key); + done(); + } + }); + source.setUrl('spec/ol/data/14-8938-5680.vector.pbf?new'); + }); + }); + + }); + }); diff --git a/test/spec/ol/vectorrendertile.test.js b/test/spec/ol/vectorrendertile.test.js index 6b80b9971e..783d9acf2d 100644 --- a/test/spec/ol/vectorrendertile.test.js +++ b/test/spec/ol/vectorrendertile.test.js @@ -116,7 +116,7 @@ describe('ol.VectorRenderTile', function() { it('#dispose() when source tiles are loaded', function(done) { const source = new VectorTileSource({ format: new GeoJSON(), - url: 'spec/ol/data/point.json', + url: 'spec/ol/data/point.json?{z}/{x}/{y}', tileGrid: createXYZ() }); source.getTileGridForProjection = function() {