Render only when we have time, and not during interaction/animation
This commit is contained in:
@@ -14,15 +14,15 @@ class Disposable {
|
|||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.disposed_ = false;
|
this.disposed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean up.
|
* Clean up.
|
||||||
*/
|
*/
|
||||||
dispose() {
|
dispose() {
|
||||||
if (!this.disposed_) {
|
if (!this.disposed) {
|
||||||
this.disposed_ = true;
|
this.disposed = true;
|
||||||
this.disposeInternal();
|
this.disposeInternal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,6 +122,12 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
*/
|
*/
|
||||||
this.renderedLayerRevision_;
|
this.renderedLayerRevision_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {Object<string, import("../../VectorImageTile").default>}
|
||||||
|
*/
|
||||||
|
this.tilesToPrepare_ = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {import("../../transform.js").Transform}
|
* @type {import("../../transform.js").Transform}
|
||||||
@@ -151,17 +157,23 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
if (tile.getState() === TileState.IDLE) {
|
if (tile.getState() === TileState.IDLE) {
|
||||||
const key = listen(tile, EventType.CHANGE, function() {
|
const key = listen(tile, EventType.CHANGE, function() {
|
||||||
if (tile.sourceTilesLoaded) {
|
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);
|
unlistenByKey(key);
|
||||||
tile.setState(TileState.LOADED);
|
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
}
|
}
|
||||||
if (tile.getState() === TileState.LOADED) {
|
if (tile.getState() === TileState.LOADED) {
|
||||||
this.createExecutorGroup_(tile, pixelRatio, projection);
|
this.updateExecutorGroup_(tile, pixelRatio, projection);
|
||||||
if (this.context) {
|
this.renderTileImage_(tile, pixelRatio, projection);
|
||||||
this.renderTileImage_(tile, pixelRatio, projection);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return tile;
|
return tile;
|
||||||
}
|
}
|
||||||
@@ -193,7 +205,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
* @param {import("../../proj/Projection.js").default} projection Projection.
|
* @param {import("../../proj/Projection.js").default} projection Projection.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
createExecutorGroup_(tile, pixelRatio, projection) {
|
updateExecutorGroup_(tile, pixelRatio, projection) {
|
||||||
const layer = /** @type {import("../../layer/Vector.js").default} */ (this.getLayer());
|
const layer = /** @type {import("../../layer/Vector.js").default} */ (this.getLayer());
|
||||||
const revision = layer.getRevision();
|
const revision = layer.getRevision();
|
||||||
const renderOrder = /** @type {import("../../render.js").OrderFunction} */ (layer.getRenderOrder()) || null;
|
const renderOrder = /** @type {import("../../render.js").OrderFunction} */ (layer.getRenderOrder()) || null;
|
||||||
@@ -413,7 +425,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
this.declutterTree_.clear();
|
this.declutterTree_.clear();
|
||||||
}
|
}
|
||||||
const viewHints = frameState.viewHints;
|
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 tiles = this.renderedTiles;
|
||||||
const tileGrid = source.getTileGridForProjection(frameState.viewState.projection);
|
const tileGrid = source.getTileGridForProjection(frameState.viewState.projection);
|
||||||
const clips = [];
|
const clips = [];
|
||||||
@@ -460,14 +472,14 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
context.clip();
|
context.clip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
executorGroup.execute(context, transform, rotation, {}, snapToPixel, replayTypes, declutterReplays);
|
executorGroup.execute(context, transform, rotation, {}, hifi, replayTypes, declutterReplays);
|
||||||
context.restore();
|
context.restore();
|
||||||
clips.push(currentClip);
|
clips.push(currentClip);
|
||||||
zs.push(currentZ);
|
zs.push(currentZ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (declutterReplays) {
|
if (declutterReplays) {
|
||||||
replayDeclutter(declutterReplays, context, rotation, snapToPixel);
|
replayDeclutter(declutterReplays, context, rotation, hifi);
|
||||||
}
|
}
|
||||||
|
|
||||||
const opacity = layerState.opacity;
|
const opacity = layerState.opacity;
|
||||||
@@ -475,6 +487,27 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
canvas.style.opacity = opacity;
|
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_;
|
return this.container_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,17 +12,17 @@ describe('ol.Disposable', function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#disposed_', function() {
|
describe('#disposed', function() {
|
||||||
|
|
||||||
it('is initially false', function() {
|
it('is initially false', function() {
|
||||||
const disposable = new Disposable();
|
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() {
|
it('is true after a call to dispose', function() {
|
||||||
const disposable = new Disposable();
|
const disposable = new Disposable();
|
||||||
disposable.dispose();
|
disposable.dispose();
|
||||||
expect(disposable.disposed_).to.be(true);
|
expect(disposable.disposed).to.be(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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 format = new GeoJSON();
|
||||||
const url = 'spec/ol/data/unavailable.json';
|
const url = 'spec/ol/data/unavailable.json';
|
||||||
let sourceTile;
|
let sourceTile;
|
||||||
@@ -47,7 +47,11 @@ describe('ol.VectorImageTile', function() {
|
|||||||
let calls = 0;
|
let calls = 0;
|
||||||
listen(tile, 'change', function(e) {
|
listen(tile, 'change', function(e) {
|
||||||
++calls;
|
++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) {
|
if (calls == 2) {
|
||||||
done();
|
done();
|
||||||
} else {
|
} else {
|
||||||
@@ -131,7 +135,7 @@ describe('ol.VectorImageTile', function() {
|
|||||||
expect(tile.getState()).to.be(TileState.ABORT);
|
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 format = new GeoJSON();
|
||||||
const url = 'spec/ol/data/point.json';
|
const url = 'spec/ol/data/point.json';
|
||||||
const tile = new VectorImageTile([0, 0, 0], 0, url, format,
|
const tile = new VectorImageTile([0, 0, 0], 0, url, format,
|
||||||
@@ -142,7 +146,8 @@ describe('ol.VectorImageTile', function() {
|
|||||||
|
|
||||||
tile.load();
|
tile.load();
|
||||||
listenOnce(tile, 'change', function() {
|
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.loadListenerKeys_.length).to.be(0);
|
||||||
expect(tile.tileKeys.length).to.be(4);
|
expect(tile.tileKeys.length).to.be(4);
|
||||||
tile.dispose();
|
tile.dispose();
|
||||||
|
|||||||
Reference in New Issue
Block a user