View / apply constraints automatically based on hints

All constraints can now function differently if they are applied during
interaction or animation.
This commit is contained in:
jahow
2019-01-12 23:47:02 +01:00
committed by Olivier Guyot
parent d991dfa54a
commit e52fab636c
5 changed files with 55 additions and 27 deletions

View File

@@ -449,9 +449,9 @@ class View extends BaseObject {
return;
}
let start = Date.now();
let center = this.getCenter().slice();
let resolution = this.getResolution();
let rotation = this.getRotation();
let center = this.targetCenter_.slice();
let resolution = this.targetResolution_;
let rotation = this.targetRotation_;
const series = [];
for (let i = 0; i < animationCount; ++i) {
const options = /** @type {AnimationOptions} */ (arguments[i]);
@@ -573,28 +573,27 @@ class View extends BaseObject {
const y1 = animation.targetCenter[1];
const x = x0 + progress * (x1 - x0);
const y = y0 + progress * (y1 - y0);
this.set(ViewProperty.CENTER, [x, y]);
this.targetCenter_ = [x, y];
}
if (animation.sourceResolution && animation.targetResolution) {
const resolution = progress === 1 ?
animation.targetResolution :
animation.sourceResolution + progress * (animation.targetResolution - animation.sourceResolution);
if (animation.anchor) {
this.set(ViewProperty.CENTER,
this.calculateCenterZoom(resolution, animation.anchor));
this.targetCenter_ = this.calculateCenterZoom(resolution, animation.anchor);
}
this.set(ViewProperty.RESOLUTION, resolution);
this.targetResolution_ = resolution;
}
if (animation.sourceRotation !== undefined && animation.targetRotation !== undefined) {
const rotation = progress === 1 ?
modulo(animation.targetRotation + Math.PI, 2 * Math.PI) - Math.PI :
animation.sourceRotation + progress * (animation.targetRotation - animation.sourceRotation);
if (animation.anchor) {
this.set(ViewProperty.CENTER,
this.calculateCenterRotate(rotation, animation.anchor));
this.targetCenter_ = this.calculateCenterRotate(rotation, animation.anchor);
}
this.set(ViewProperty.ROTATION, rotation);
this.targetRotation_ = rotation;
}
this.applyParameters_(true);
more = true;
if (!animation.complete) {
break;
@@ -623,10 +622,10 @@ class View extends BaseObject {
*/
calculateCenterRotate(rotation, anchor) {
let center;
const currentCenter = this.getCenter();
const currentCenter = this.targetCenter_;
if (currentCenter !== undefined) {
center = [currentCenter[0] - anchor[0], currentCenter[1] - anchor[1]];
rotateCoordinate(center, rotation - this.getRotation());
rotateCoordinate(center, rotation - this.targetRotation_);
addCoordinate(center, anchor);
}
return center;
@@ -639,8 +638,8 @@ class View extends BaseObject {
*/
calculateCenterZoom(resolution, anchor) {
let center;
const currentCenter = this.getCenter();
const currentResolution = this.getResolution();
const currentCenter = this.targetCenter_;
const currentResolution = this.targetResolution_;
if (currentCenter !== undefined && currentResolution !== undefined) {
const x = anchor[0] - resolution * (anchor[0] - currentCenter[0]) / currentResolution;
const y = anchor[1] - resolution * (anchor[1] - currentCenter[1]) / currentResolution;
@@ -917,7 +916,7 @@ class View extends BaseObject {
*/
getZoom() {
let zoom;
const resolution = this.getResolution();
const resolution = this.targetResolution_;
if (resolution !== undefined) {
zoom = this.getZoomForResolution(resolution);
}
@@ -1059,8 +1058,9 @@ class View extends BaseObject {
easing: options.easing
}, callback);
} else {
this.setResolution(resolution);
this.setCenter(center);
this.targetResolution_ = resolution;
this.targetCenter_ = center;
this.applyParameters_(false, true);
animationCallback(callback, true);
}
}
@@ -1167,14 +1167,21 @@ class View extends BaseObject {
/**
* Recompute rotation/resolution/center based on target values.
* @param {boolean=} opt_doNotCancelAnims Do not cancel animations.
* @param {boolean=} opt_forceMoving Apply constraints as if the view is moving.
* @private
*/
applyParameters_() {
this.set(ViewProperty.ROTATION, this.targetRotation_);
this.set(ViewProperty.RESOLUTION, this.targetResolution_);
this.set(ViewProperty.CENTER, this.targetCenter_);
applyParameters_(opt_doNotCancelAnims, opt_forceMoving) {
const isMoving = this.getAnimating() || this.getInteracting() || opt_forceMoving;
const newRotation = this.constraints_.rotation(this.targetRotation_, 0, isMoving);
const newResolution = this.constraints_.resolution(this.targetResolution_, 0, 0, isMoving);
const newCenter = this.constraints_.center(this.targetCenter_, isMoving);
if (this.getAnimating()) {
this.set(ViewProperty.ROTATION, newRotation);
this.set(ViewProperty.RESOLUTION, newResolution);
this.set(ViewProperty.CENTER, newCenter);
if (this.getAnimating() && !opt_doNotCancelAnims) {
this.cancelAnimations();
}
}

View File

@@ -19,7 +19,7 @@ export function createExtent(extent) {
* @param {import("./coordinate.js").Coordinate=} center Center.
* @return {import("./coordinate.js").Coordinate|undefined} Center.
*/
function(center) {
function(center, opt_isMoving) {
if (center) {
return [
clamp(center[0], extent[0], extent[2]),

View File

@@ -22,8 +22,14 @@ export function createSnapToResolutions(resolutions) {
* @param {number} direction Direction.
* @return {number|undefined} Resolution.
*/
function(resolution, delta, direction) {
function(resolution, delta, direction, opt_isMoving) {
if (resolution !== undefined) {
// during interacting or animating, allow intermediary values
if (opt_isMoving) {
// TODO: actually take delta and direction into account
return resolution;
}
let z = linearFindNearest(resolutions, resolution, direction);
z = clamp(z + delta, 0, resolutions.length - 1);
const index = Math.floor(z);
@@ -55,8 +61,14 @@ export function createSnapToPower(power, maxResolution, opt_maxLevel) {
* @param {number} direction Direction.
* @return {number|undefined} Resolution.
*/
function(resolution, delta, direction) {
function(resolution, delta, direction, opt_isMoving) {
if (resolution !== undefined) {
// during interacting or animating, allow intermediary values
if (opt_isMoving) {
// TODO: actually take delta and direction into account
return resolution;
}
const offset = -direction / 2 + 0.5;
const oldLevel = Math.floor(
Math.log(maxResolution / resolution) / Math.log(power) + offset);

View File

@@ -49,7 +49,11 @@ export function createSnapToN(n) {
* @param {number} delta Delta.
* @return {number|undefined} Rotation.
*/
function(rotation, delta) {
function(rotation, delta, opt_isMoving) {
if (opt_isMoving) {
return rotation;
}
if (rotation !== undefined) {
rotation = Math.floor((rotation + delta) / theta + 0.5) * theta;
return rotation;
@@ -72,7 +76,11 @@ export function createSnapToZero(opt_tolerance) {
* @param {number} delta Delta.
* @return {number|undefined} Rotation.
*/
function(rotation, delta) {
function(rotation, delta, opt_isMoving) {
if (opt_isMoving) {
return rotation;
}
if (rotation !== undefined) {
if (Math.abs(rotation + delta) <= tolerance) {
return 0;

View File

@@ -365,6 +365,7 @@ describe('ol.View', function() {
it('applies the current resolution if resolution was originally supplied', function() {
const view = new View({
center: [0, 0],
maxResolution: 2000,
resolution: 1000
});
view.setResolution(500);