Enqueue tiles at the next resolution in the animation
This commit is contained in:
@@ -48,6 +48,7 @@ import {removeNode} from './dom.js';
|
|||||||
* @property {import("./transform.js").Transform} coordinateToPixelTransform CoordinateToPixelTransform.
|
* @property {import("./transform.js").Transform} coordinateToPixelTransform CoordinateToPixelTransform.
|
||||||
* @property {import("rbush").default} declutterTree DeclutterTree.
|
* @property {import("rbush").default} declutterTree DeclutterTree.
|
||||||
* @property {null|import("./extent.js").Extent} extent Extent.
|
* @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 {number} index Index.
|
||||||
* @property {Array<import("./layer/Layer.js").State>} layerStatesArray LayerStatesArray.
|
* @property {Array<import("./layer/Layer.js").State>} layerStatesArray LayerStatesArray.
|
||||||
* @property {number} layerIndex LayerIndex.
|
* @property {number} layerIndex LayerIndex.
|
||||||
@@ -1436,6 +1437,18 @@ class PluggableMap extends BaseObject {
|
|||||||
viewHints: viewHints,
|
viewHints: viewHints,
|
||||||
wantedTiles: {},
|
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;
|
this.frameState_ = frameState;
|
||||||
|
|||||||
+34
-1
@@ -208,6 +208,9 @@ import {fromExtent as polygonFromExtent} from './geom/Polygon.js';
|
|||||||
* @property {import("./coordinate.js").Coordinate} center Center.
|
* @property {import("./coordinate.js").Coordinate} center Center.
|
||||||
* @property {import("./proj/Projection.js").default} projection Projection.
|
* @property {import("./proj/Projection.js").default} projection Projection.
|
||||||
* @property {number} resolution Resolution.
|
* @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} rotation Rotation.
|
||||||
* @property {number} zoom Zoom.
|
* @property {number} zoom Zoom.
|
||||||
*/
|
*/
|
||||||
@@ -374,6 +377,24 @@ class View extends BaseObject {
|
|||||||
*/
|
*/
|
||||||
this.targetRotation_;
|
this.targetRotation_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {import("./coordinate.js").Coordinate}
|
||||||
|
*/
|
||||||
|
this.nextCenter_ = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
this.nextResolution_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
this.nextRotation_;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {import("./coordinate.js").Coordinate|undefined}
|
* @type {import("./coordinate.js").Coordinate|undefined}
|
||||||
@@ -714,6 +735,9 @@ class View extends BaseObject {
|
|||||||
}
|
}
|
||||||
this.animations_.length = 0;
|
this.animations_.length = 0;
|
||||||
this.cancelAnchor_ = anchor;
|
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 y0 = animation.sourceCenter[1];
|
||||||
const x1 = animation.targetCenter[0];
|
const x1 = animation.targetCenter[0];
|
||||||
const y1 = animation.targetCenter[1];
|
const y1 = animation.targetCenter[1];
|
||||||
|
this.nextCenter_ = animation.targetCenter;
|
||||||
const x = x0 + progress * (x1 - x0);
|
const x = x0 + progress * (x1 - x0);
|
||||||
const y = y0 + progress * (y1 - y0);
|
const y = y0 + progress * (y1 - y0);
|
||||||
this.targetCenter_ = [x, y];
|
this.targetCenter_ = [x, y];
|
||||||
@@ -776,6 +801,7 @@ class View extends BaseObject {
|
|||||||
animation.anchor
|
animation.anchor
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
this.nextResolution_ = animation.targetResolution;
|
||||||
this.targetResolution_ = resolution;
|
this.targetResolution_ = resolution;
|
||||||
this.applyTargetState_(true);
|
this.applyTargetState_(true);
|
||||||
}
|
}
|
||||||
@@ -800,6 +826,7 @@ class View extends BaseObject {
|
|||||||
animation.anchor
|
animation.anchor
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
this.nextRotation_ = animation.targetRotation;
|
||||||
this.targetRotation_ = rotation;
|
this.targetRotation_ = rotation;
|
||||||
}
|
}
|
||||||
this.applyTargetState_(true);
|
this.applyTargetState_(true);
|
||||||
@@ -811,6 +838,9 @@ class View extends BaseObject {
|
|||||||
if (seriesComplete) {
|
if (seriesComplete) {
|
||||||
this.animations_[i] = null;
|
this.animations_[i] = null;
|
||||||
this.setHint(ViewHint.ANIMATING, -1);
|
this.setHint(ViewHint.ANIMATING, -1);
|
||||||
|
this.nextCenter_ = null;
|
||||||
|
this.nextResolution_ = NaN;
|
||||||
|
this.nextRotation_ = NaN;
|
||||||
const callback = series[0].callback;
|
const callback = series[0].callback;
|
||||||
if (callback) {
|
if (callback) {
|
||||||
animationCallback(callback, true);
|
animationCallback(callback, true);
|
||||||
@@ -1191,7 +1221,7 @@ class View extends BaseObject {
|
|||||||
*/
|
*/
|
||||||
getState() {
|
getState() {
|
||||||
const projection = this.getProjection();
|
const projection = this.getProjection();
|
||||||
const resolution = /** @type {number} */ (this.getResolution());
|
const resolution = this.getResolution();
|
||||||
const rotation = this.getRotation();
|
const rotation = this.getRotation();
|
||||||
let center = /** @type {import("./coordinate.js").Coordinate} */ (
|
let center = /** @type {import("./coordinate.js").Coordinate} */ (
|
||||||
this.getCenterInternal()
|
this.getCenterInternal()
|
||||||
@@ -1211,6 +1241,9 @@ class View extends BaseObject {
|
|||||||
center: center.slice(0),
|
center: center.slice(0),
|
||||||
projection: projection !== undefined ? projection : null,
|
projection: projection !== undefined ? projection : null,
|
||||||
resolution: resolution,
|
resolution: resolution,
|
||||||
|
nextCenter: this.nextCenter_,
|
||||||
|
nextResolution: this.nextResolution_,
|
||||||
|
nextRotation: this.nextRotation_,
|
||||||
rotation: rotation,
|
rotation: rotation,
|
||||||
zoom: this.getZoom(),
|
zoom: this.getZoom(),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -82,13 +82,12 @@ function addTileTextureToLookup(tileTexturesByZ, tileTexture, z) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
|
* @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];
|
const layerState = frameState.layerStatesArray[frameState.layerIndex];
|
||||||
let extent = frameState.extent;
|
|
||||||
if (layerState.extent) {
|
if (layerState.extent) {
|
||||||
extent = getIntersection(
|
extent = getIntersection(
|
||||||
extent,
|
extent,
|
||||||
@@ -213,7 +212,7 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
|
|||||||
* @return {boolean} Layer is ready to be rendered.
|
* @return {boolean} Layer is ready to be rendered.
|
||||||
*/
|
*/
|
||||||
prepareFrame(frameState) {
|
prepareFrame(frameState) {
|
||||||
if (isEmpty(getRenderExtent(frameState))) {
|
if (isEmpty(getRenderExtent(frameState, frameState.extent))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const source = this.getLayer().getSource();
|
const source = this.getLayer().getSource();
|
||||||
@@ -223,30 +222,11 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
|
|||||||
return source.getState() === State.READY;
|
return source.getState() === State.READY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
enqueueTiles(frameState, extent, z, tileTexturesByZ) {
|
||||||
* 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 viewState = frameState.viewState;
|
||||||
const layerState = frameState.layerStatesArray[frameState.layerIndex];
|
|
||||||
const extent = getRenderExtent(frameState);
|
|
||||||
const tileLayer = this.getLayer();
|
const tileLayer = this.getLayer();
|
||||||
const tileSource = tileLayer.getSource();
|
const tileSource = tileLayer.getSource();
|
||||||
const tileGrid = tileSource.getTileGridForProjection(viewState.projection);
|
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 tileTextureCache = this.tileTextureCache_;
|
||||||
const tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z);
|
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
|
* A lookup of alpha values for tiles at the target rendering resolution
|
||||||
@@ -474,6 +490,7 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
|
|||||||
this.renderedOpacity_ = opacity;
|
this.renderedOpacity_ = opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const tileTextureCache = this.tileTextureCache_;
|
||||||
while (tileTextureCache.canExpireCache()) {
|
while (tileTextureCache.canExpireCache()) {
|
||||||
const tileTexture = tileTextureCache.pop();
|
const tileTexture = tileTextureCache.pop();
|
||||||
tileTexture.dispose();
|
tileTexture.dispose();
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import ViewHint from '../../../../src/ol/ViewHint.js';
|
|||||||
import {clearUserProjection, useGeographic} from '../../../../src/ol/proj.js';
|
import {clearUserProjection, useGeographic} from '../../../../src/ol/proj.js';
|
||||||
import {createEmpty} from '../../../../src/ol/extent.js';
|
import {createEmpty} from '../../../../src/ol/extent.js';
|
||||||
|
|
||||||
describe('ol.View', function () {
|
describe('ol/View', function () {
|
||||||
describe('constructor (defaults)', function () {
|
describe('constructor (defaults)', function () {
|
||||||
let view;
|
let view;
|
||||||
|
|
||||||
@@ -688,13 +688,15 @@ describe('ol.View', function () {
|
|||||||
},
|
},
|
||||||
function (complete) {
|
function (complete) {
|
||||||
expect(complete).to.be(true);
|
expect(complete).to.be(true);
|
||||||
|
expect(isNaN(view.nextResolution_)).to.be(true);
|
||||||
expect(view.getCenter()).to.eql([0, 0]);
|
expect(view.getCenter()).to.eql([0, 0]);
|
||||||
expect(view.getZoom()).to.eql(4);
|
expect(view.getZoom()).to.eql(4);
|
||||||
expect(view.getAnimating()).to.eql(false);
|
expect(view.getAnimating()).to.be(false);
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
expect(view.getAnimating()).to.eql(true);
|
expect(view.getAnimating()).to.eql(true);
|
||||||
|
expect(isNaN(view.nextResolution_)).to.be(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('allows duration to be zero', function (done) {
|
it('allows duration to be zero', function (done) {
|
||||||
Reference in New Issue
Block a user