Enqueue tiles at the next resolution in the animation

This commit is contained in:
Tim Schaub
2021-09-22 22:10:18 +00:00
parent 2435321133
commit 4dc66ef8e3
4 changed files with 93 additions and 28 deletions

View File

@@ -48,6 +48,7 @@ import {removeNode} from './dom.js';
* @property {import("./transform.js").Transform} coordinateToPixelTransform CoordinateToPixelTransform.
* @property {import("rbush").default} declutterTree DeclutterTree.
* @property {null|import("./extent.js").Extent} extent Extent.
* @property {import("./extent.js").Extent} [nextExtent] Next extent during an animation series.
* @property {number} index Index.
* @property {Array<import("./layer/Layer.js").State>} layerStatesArray LayerStatesArray.
* @property {number} layerIndex LayerIndex.
@@ -1436,6 +1437,18 @@ class PluggableMap extends BaseObject {
viewHints: viewHints,
wantedTiles: {},
};
if (viewState.nextCenter && viewState.nextResolution) {
const rotation = isNaN(viewState.nextRotation)
? viewState.rotation
: viewState.nextRotation;
frameState.nextExtent = getForViewAndSize(
viewState.nextCenter,
viewState.nextResolution,
rotation,
size
);
}
}
this.frameState_ = frameState;

View File

@@ -208,6 +208,9 @@ import {fromExtent as polygonFromExtent} from './geom/Polygon.js';
* @property {import("./coordinate.js").Coordinate} center Center.
* @property {import("./proj/Projection.js").default} projection Projection.
* @property {number} resolution Resolution.
* @property {import("./coordinate.js").Coordinate} [nextCenter] The next center during an animation series.
* @property {number} [nextResolution] The next resolution during an animation series.
* @property {number} [nextRotation] The next rotation during an animation series.
* @property {number} rotation Rotation.
* @property {number} zoom Zoom.
*/
@@ -374,6 +377,24 @@ class View extends BaseObject {
*/
this.targetRotation_;
/**
* @private
* @type {import("./coordinate.js").Coordinate}
*/
this.nextCenter_ = null;
/**
* @private
* @type {number}
*/
this.nextResolution_;
/**
* @private
* @type {number}
*/
this.nextRotation_;
/**
* @private
* @type {import("./coordinate.js").Coordinate|undefined}
@@ -714,6 +735,9 @@ class View extends BaseObject {
}
this.animations_.length = 0;
this.cancelAnchor_ = anchor;
this.nextCenter_ = null;
this.nextResolution_ = NaN;
this.nextRotation_ = NaN;
}
/**
@@ -752,6 +776,7 @@ class View extends BaseObject {
const y0 = animation.sourceCenter[1];
const x1 = animation.targetCenter[0];
const y1 = animation.targetCenter[1];
this.nextCenter_ = animation.targetCenter;
const x = x0 + progress * (x1 - x0);
const y = y0 + progress * (y1 - y0);
this.targetCenter_ = [x, y];
@@ -776,6 +801,7 @@ class View extends BaseObject {
animation.anchor
);
}
this.nextResolution_ = animation.targetResolution;
this.targetResolution_ = resolution;
this.applyTargetState_(true);
}
@@ -800,6 +826,7 @@ class View extends BaseObject {
animation.anchor
);
}
this.nextRotation_ = animation.targetRotation;
this.targetRotation_ = rotation;
}
this.applyTargetState_(true);
@@ -811,6 +838,9 @@ class View extends BaseObject {
if (seriesComplete) {
this.animations_[i] = null;
this.setHint(ViewHint.ANIMATING, -1);
this.nextCenter_ = null;
this.nextResolution_ = NaN;
this.nextRotation_ = NaN;
const callback = series[0].callback;
if (callback) {
animationCallback(callback, true);
@@ -1191,7 +1221,7 @@ class View extends BaseObject {
*/
getState() {
const projection = this.getProjection();
const resolution = /** @type {number} */ (this.getResolution());
const resolution = this.getResolution();
const rotation = this.getRotation();
let center = /** @type {import("./coordinate.js").Coordinate} */ (
this.getCenterInternal()
@@ -1211,6 +1241,9 @@ class View extends BaseObject {
center: center.slice(0),
projection: projection !== undefined ? projection : null,
resolution: resolution,
nextCenter: this.nextCenter_,
nextResolution: this.nextResolution_,
nextRotation: this.nextRotation_,
rotation: rotation,
zoom: this.getZoom(),
};

View File

@@ -82,13 +82,12 @@ function addTileTextureToLookup(tileTexturesByZ, tileTexture, z) {
}
/**
*
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
* @return {import("../../extent.js").Extent} Extent.
* @param {import("../../extent.js").Extent} extent The frame extent.
* @return {import("../../extent.js").Extent} Frame extent intersected with layer extents.
*/
function getRenderExtent(frameState) {
function getRenderExtent(frameState, extent) {
const layerState = frameState.layerStatesArray[frameState.layerIndex];
let extent = frameState.extent;
if (layerState.extent) {
extent = getIntersection(
extent,
@@ -213,7 +212,7 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
* @return {boolean} Layer is ready to be rendered.
*/
prepareFrame(frameState) {
if (isEmpty(getRenderExtent(frameState))) {
if (isEmpty(getRenderExtent(frameState, frameState.extent))) {
return false;
}
const source = this.getLayer().getSource();
@@ -223,30 +222,11 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
return source.getState() === State.READY;
}
/**
* Render the layer.
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
* @return {HTMLElement} The rendered element.
*/
renderFrame(frameState) {
this.preRender(frameState);
enqueueTiles(frameState, extent, z, tileTexturesByZ) {
const viewState = frameState.viewState;
const layerState = frameState.layerStatesArray[frameState.layerIndex];
const extent = getRenderExtent(frameState);
const tileLayer = this.getLayer();
const tileSource = tileLayer.getSource();
const tileGrid = tileSource.getTileGridForProjection(viewState.projection);
const z = tileGrid.getZForResolution(
viewState.resolution,
tileSource.zDirection
);
/**
* @type {Object<string, Array<import("../../webgl/TileTexture.js").default>>}
*/
const tileTexturesByZ = {};
const tileTextureCache = this.tileTextureCache_;
const tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z);
@@ -304,6 +284,42 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
}
}
}
}
/**
* Render the layer.
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
* @return {HTMLElement} The rendered element.
*/
renderFrame(frameState) {
this.preRender(frameState);
const viewState = frameState.viewState;
const layerState = frameState.layerStatesArray[frameState.layerIndex];
const extent = getRenderExtent(frameState, frameState.extent);
const tileLayer = this.getLayer();
const tileSource = tileLayer.getSource();
const tileGrid = tileSource.getTileGridForProjection(viewState.projection);
const z = tileGrid.getZForResolution(
viewState.resolution,
tileSource.zDirection
);
/**
* @type {Object<string, Array<import("../../webgl/TileTexture.js").default>>}
*/
const tileTexturesByZ = {};
if (frameState.nextExtent) {
const targetZ = tileGrid.getZForResolution(
viewState.nextResolution,
tileSource.zDirection
);
const nextExtent = getRenderExtent(frameState, frameState.nextExtent);
this.enqueueTiles(frameState, nextExtent, targetZ, tileTexturesByZ);
}
this.enqueueTiles(frameState, extent, z, tileTexturesByZ);
/**
* A lookup of alpha values for tiles at the target rendering resolution
@@ -474,6 +490,7 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
this.renderedOpacity_ = opacity;
}
const tileTextureCache = this.tileTextureCache_;
while (tileTextureCache.canExpireCache()) {
const tileTexture = tileTextureCache.pop();
tileTexture.dispose();