diff --git a/src/ol/source/VectorTile.js b/src/ol/source/VectorTile.js index 957ca34f34..fc3ee620c7 100644 --- a/src/ol/source/VectorTile.js +++ b/src/ol/source/VectorTile.js @@ -18,7 +18,7 @@ import { createXYZ, extentFromProjection, } from '../tilegrid.js'; -import {fromKey, getKeyZXY} from '../tilecoord.js'; +import {fromKey, getCacheKeyForTileKey, getKeyZXY} from '../tilecoord.js'; import {isEmpty} from '../obj.js'; import {loadFeaturesXhr} from '../featureloader.js'; import {toSize} from '../size.js'; @@ -237,8 +237,19 @@ class VectorTile extends UrlTile { * @param {!Object} usedTiles Used tiles. */ expireCache(projection, usedTiles) { + const tileCache = this.getTileCacheForProjection(projection); + const usedSourceTiles = Object.keys(usedTiles).reduce((acc, key) => { + const cacheKey = getCacheKeyForTileKey(key); + if (tileCache.containsKey(cacheKey)) { + const sourceTiles = tileCache.get(cacheKey).sourceTiles; + for (let i = 0, ii = sourceTiles.length; i < ii; ++i) { + acc[sourceTiles[i].getKey()] = true; + } + } + return acc; + }, {}); super.expireCache(projection, usedTiles); - this.sourceTileCache.expireCache({}); + this.sourceTileCache.expireCache(usedSourceTiles); } /** @@ -281,15 +292,7 @@ class VectorTile extends UrlTile { ); tile.sourceTiles.push(sourceTile); const sourceTileState = sourceTile.getState(); - if (sourceTileState === TileState.IDLE) { - sourceTile.extent = sourceTileGrid.getTileCoordExtent( - sourceTileCoord - ); - sourceTile.projection = projection; - sourceTile.resolution = sourceTileGrid.getResolution( - sourceTileCoord[0] - ); - this.sourceTileCache.set(tileUrl, sourceTile); + if (sourceTileState < TileState.LOADED) { const listenChange = (event) => { this.handleTileChange(event); const state = sourceTile.getState(); @@ -318,6 +321,16 @@ class VectorTile extends UrlTile { }; sourceTile.addEventListener(EventType.CHANGE, listenChange); tile.loadingSourceTiles++; + } + if (sourceTileState === TileState.IDLE) { + sourceTile.extent = sourceTileGrid.getTileCoordExtent( + sourceTileCoord + ); + sourceTile.projection = projection; + sourceTile.resolution = sourceTileGrid.getResolution( + sourceTileCoord[0] + ); + this.sourceTileCache.set(tileUrl, sourceTile); sourceTile.load(); } }); @@ -458,6 +471,9 @@ class VectorTile extends UrlTile { */ updateCacheSize(tileCount, projection) { super.updateCacheSize(tileCount * 2, projection); + this.sourceTileCache.highWaterMark = this.getTileCacheForProjection( + projection + ).highWaterMark; } } diff --git a/src/ol/tilecoord.js b/src/ol/tilecoord.js index fbd65e6db5..5552774df7 100644 --- a/src/ol/tilecoord.js +++ b/src/ol/tilecoord.js @@ -46,6 +46,19 @@ export function getKey(tileCoord) { return getKeyZXY(tileCoord[0], tileCoord[1], tileCoord[2]); } +/** + * Get the tile cache key for a tile key obtained through `tile.getKey()`. + * @param {string} tileKey The tile key. + * @return {string} The cache key. + */ +export function getCacheKeyForTileKey(tileKey) { + const [z, x, y] = tileKey + .substring(tileKey.lastIndexOf('/') + 1, tileKey.length) + .split(',') + .map(Number); + return getKeyZXY(z, x, y); +} + /** * Get a tile coord given a key. * @param {string} key The tile coord key. diff --git a/test/browser/spec/ol/source/vectortile.test.js b/test/browser/spec/ol/source/vectortile.test.js index 290938c3bb..949c1f0e59 100644 --- a/test/browser/spec/ol/source/vectortile.test.js +++ b/test/browser/spec/ol/source/vectortile.test.js @@ -183,6 +183,48 @@ describe('ol.source.VectorTile', function () { }); tile.load(); }); + it('triggers events and loads source tile properly for wrapX counterpart', function (done) { + const tile1 = source.getTile( + 14, + 8938, + 5680, + 1, + getProjection('EPSG:3857') + ); + const tile2 = source.getTile( + 14, + 8938 + Math.pow(2, 14), + 5680, + 1, + getProjection('EPSG:3857') + ); + expect(tile2.wrappedTileCoord).to.eql([14, 8938, 5680]); + let loadstart = 0; + source.on('tileloadstart', function () { + ++loadstart; + }); + let loadend = 0; + source.on('tileloadend', function (e) { + ++loadend; + }); + let loaded = 0; + [tile1, tile2].forEach((tile) => { + tile.addEventListener('change', (e) => { + if (e.target.getState() === TileState.LOADED) { + const sourceTiles = e.target.getSourceTiles(); + expect(sourceTiles.length).to.be(1); + expect(sourceTiles[0].getState()).to.be(TileState.LOADED); + ++loaded; + if (loaded === 2) { + expect(loadstart).to.be(1); + expect(loadend).to.be(1); + done(); + } + } + }); + tile.load(); + }); + }); }); describe('different source and render tile grids', function () { @@ -267,6 +309,18 @@ describe('ol.source.VectorTile', function () { done(); }, 0); }); + + it('adjusts the tile cache size', function (done) { + map.renderSync(); + setTimeout(function () { + expect( + source.getTileCacheForProjection(map.getView().getProjection()) + .highWaterMark + ).to.be(2); + expect(source.sourceTileCache.highWaterMark).to.be(2); + done(); + }, 0); + }); }); it('does not fill up the tile queue', function (done) {