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:
+29
-22
@@ -449,9 +449,9 @@ class View extends BaseObject {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let start = Date.now();
|
let start = Date.now();
|
||||||
let center = this.getCenter().slice();
|
let center = this.targetCenter_.slice();
|
||||||
let resolution = this.getResolution();
|
let resolution = this.targetResolution_;
|
||||||
let rotation = this.getRotation();
|
let rotation = this.targetRotation_;
|
||||||
const series = [];
|
const series = [];
|
||||||
for (let i = 0; i < animationCount; ++i) {
|
for (let i = 0; i < animationCount; ++i) {
|
||||||
const options = /** @type {AnimationOptions} */ (arguments[i]);
|
const options = /** @type {AnimationOptions} */ (arguments[i]);
|
||||||
@@ -573,28 +573,27 @@ class View extends BaseObject {
|
|||||||
const y1 = animation.targetCenter[1];
|
const y1 = animation.targetCenter[1];
|
||||||
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.set(ViewProperty.CENTER, [x, y]);
|
this.targetCenter_ = [x, y];
|
||||||
}
|
}
|
||||||
if (animation.sourceResolution && animation.targetResolution) {
|
if (animation.sourceResolution && animation.targetResolution) {
|
||||||
const resolution = progress === 1 ?
|
const resolution = progress === 1 ?
|
||||||
animation.targetResolution :
|
animation.targetResolution :
|
||||||
animation.sourceResolution + progress * (animation.targetResolution - animation.sourceResolution);
|
animation.sourceResolution + progress * (animation.targetResolution - animation.sourceResolution);
|
||||||
if (animation.anchor) {
|
if (animation.anchor) {
|
||||||
this.set(ViewProperty.CENTER,
|
this.targetCenter_ = this.calculateCenterZoom(resolution, animation.anchor);
|
||||||
this.calculateCenterZoom(resolution, animation.anchor));
|
|
||||||
}
|
}
|
||||||
this.set(ViewProperty.RESOLUTION, resolution);
|
this.targetResolution_ = resolution;
|
||||||
}
|
}
|
||||||
if (animation.sourceRotation !== undefined && animation.targetRotation !== undefined) {
|
if (animation.sourceRotation !== undefined && animation.targetRotation !== undefined) {
|
||||||
const rotation = progress === 1 ?
|
const rotation = progress === 1 ?
|
||||||
modulo(animation.targetRotation + Math.PI, 2 * Math.PI) - Math.PI :
|
modulo(animation.targetRotation + Math.PI, 2 * Math.PI) - Math.PI :
|
||||||
animation.sourceRotation + progress * (animation.targetRotation - animation.sourceRotation);
|
animation.sourceRotation + progress * (animation.targetRotation - animation.sourceRotation);
|
||||||
if (animation.anchor) {
|
if (animation.anchor) {
|
||||||
this.set(ViewProperty.CENTER,
|
this.targetCenter_ = this.calculateCenterRotate(rotation, animation.anchor);
|
||||||
this.calculateCenterRotate(rotation, animation.anchor));
|
|
||||||
}
|
}
|
||||||
this.set(ViewProperty.ROTATION, rotation);
|
this.targetRotation_ = rotation;
|
||||||
}
|
}
|
||||||
|
this.applyParameters_(true);
|
||||||
more = true;
|
more = true;
|
||||||
if (!animation.complete) {
|
if (!animation.complete) {
|
||||||
break;
|
break;
|
||||||
@@ -623,10 +622,10 @@ class View extends BaseObject {
|
|||||||
*/
|
*/
|
||||||
calculateCenterRotate(rotation, anchor) {
|
calculateCenterRotate(rotation, anchor) {
|
||||||
let center;
|
let center;
|
||||||
const currentCenter = this.getCenter();
|
const currentCenter = this.targetCenter_;
|
||||||
if (currentCenter !== undefined) {
|
if (currentCenter !== undefined) {
|
||||||
center = [currentCenter[0] - anchor[0], currentCenter[1] - anchor[1]];
|
center = [currentCenter[0] - anchor[0], currentCenter[1] - anchor[1]];
|
||||||
rotateCoordinate(center, rotation - this.getRotation());
|
rotateCoordinate(center, rotation - this.targetRotation_);
|
||||||
addCoordinate(center, anchor);
|
addCoordinate(center, anchor);
|
||||||
}
|
}
|
||||||
return center;
|
return center;
|
||||||
@@ -639,8 +638,8 @@ class View extends BaseObject {
|
|||||||
*/
|
*/
|
||||||
calculateCenterZoom(resolution, anchor) {
|
calculateCenterZoom(resolution, anchor) {
|
||||||
let center;
|
let center;
|
||||||
const currentCenter = this.getCenter();
|
const currentCenter = this.targetCenter_;
|
||||||
const currentResolution = this.getResolution();
|
const currentResolution = this.targetResolution_;
|
||||||
if (currentCenter !== undefined && currentResolution !== undefined) {
|
if (currentCenter !== undefined && currentResolution !== undefined) {
|
||||||
const x = anchor[0] - resolution * (anchor[0] - currentCenter[0]) / currentResolution;
|
const x = anchor[0] - resolution * (anchor[0] - currentCenter[0]) / currentResolution;
|
||||||
const y = anchor[1] - resolution * (anchor[1] - currentCenter[1]) / currentResolution;
|
const y = anchor[1] - resolution * (anchor[1] - currentCenter[1]) / currentResolution;
|
||||||
@@ -917,7 +916,7 @@ class View extends BaseObject {
|
|||||||
*/
|
*/
|
||||||
getZoom() {
|
getZoom() {
|
||||||
let zoom;
|
let zoom;
|
||||||
const resolution = this.getResolution();
|
const resolution = this.targetResolution_;
|
||||||
if (resolution !== undefined) {
|
if (resolution !== undefined) {
|
||||||
zoom = this.getZoomForResolution(resolution);
|
zoom = this.getZoomForResolution(resolution);
|
||||||
}
|
}
|
||||||
@@ -1059,8 +1058,9 @@ class View extends BaseObject {
|
|||||||
easing: options.easing
|
easing: options.easing
|
||||||
}, callback);
|
}, callback);
|
||||||
} else {
|
} else {
|
||||||
this.setResolution(resolution);
|
this.targetResolution_ = resolution;
|
||||||
this.setCenter(center);
|
this.targetCenter_ = center;
|
||||||
|
this.applyParameters_(false, true);
|
||||||
animationCallback(callback, true);
|
animationCallback(callback, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1167,14 +1167,21 @@ class View extends BaseObject {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Recompute rotation/resolution/center based on target values.
|
* 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
|
* @private
|
||||||
*/
|
*/
|
||||||
applyParameters_() {
|
applyParameters_(opt_doNotCancelAnims, opt_forceMoving) {
|
||||||
this.set(ViewProperty.ROTATION, this.targetRotation_);
|
const isMoving = this.getAnimating() || this.getInteracting() || opt_forceMoving;
|
||||||
this.set(ViewProperty.RESOLUTION, this.targetResolution_);
|
const newRotation = this.constraints_.rotation(this.targetRotation_, 0, isMoving);
|
||||||
this.set(ViewProperty.CENTER, this.targetCenter_);
|
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();
|
this.cancelAnimations();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export function createExtent(extent) {
|
|||||||
* @param {import("./coordinate.js").Coordinate=} center Center.
|
* @param {import("./coordinate.js").Coordinate=} center Center.
|
||||||
* @return {import("./coordinate.js").Coordinate|undefined} Center.
|
* @return {import("./coordinate.js").Coordinate|undefined} Center.
|
||||||
*/
|
*/
|
||||||
function(center) {
|
function(center, opt_isMoving) {
|
||||||
if (center) {
|
if (center) {
|
||||||
return [
|
return [
|
||||||
clamp(center[0], extent[0], extent[2]),
|
clamp(center[0], extent[0], extent[2]),
|
||||||
|
|||||||
@@ -22,8 +22,14 @@ export function createSnapToResolutions(resolutions) {
|
|||||||
* @param {number} direction Direction.
|
* @param {number} direction Direction.
|
||||||
* @return {number|undefined} Resolution.
|
* @return {number|undefined} Resolution.
|
||||||
*/
|
*/
|
||||||
function(resolution, delta, direction) {
|
function(resolution, delta, direction, opt_isMoving) {
|
||||||
if (resolution !== undefined) {
|
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);
|
let z = linearFindNearest(resolutions, resolution, direction);
|
||||||
z = clamp(z + delta, 0, resolutions.length - 1);
|
z = clamp(z + delta, 0, resolutions.length - 1);
|
||||||
const index = Math.floor(z);
|
const index = Math.floor(z);
|
||||||
@@ -55,8 +61,14 @@ export function createSnapToPower(power, maxResolution, opt_maxLevel) {
|
|||||||
* @param {number} direction Direction.
|
* @param {number} direction Direction.
|
||||||
* @return {number|undefined} Resolution.
|
* @return {number|undefined} Resolution.
|
||||||
*/
|
*/
|
||||||
function(resolution, delta, direction) {
|
function(resolution, delta, direction, opt_isMoving) {
|
||||||
if (resolution !== undefined) {
|
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 offset = -direction / 2 + 0.5;
|
||||||
const oldLevel = Math.floor(
|
const oldLevel = Math.floor(
|
||||||
Math.log(maxResolution / resolution) / Math.log(power) + offset);
|
Math.log(maxResolution / resolution) / Math.log(power) + offset);
|
||||||
|
|||||||
@@ -49,7 +49,11 @@ export function createSnapToN(n) {
|
|||||||
* @param {number} delta Delta.
|
* @param {number} delta Delta.
|
||||||
* @return {number|undefined} Rotation.
|
* @return {number|undefined} Rotation.
|
||||||
*/
|
*/
|
||||||
function(rotation, delta) {
|
function(rotation, delta, opt_isMoving) {
|
||||||
|
if (opt_isMoving) {
|
||||||
|
return rotation;
|
||||||
|
}
|
||||||
|
|
||||||
if (rotation !== undefined) {
|
if (rotation !== undefined) {
|
||||||
rotation = Math.floor((rotation + delta) / theta + 0.5) * theta;
|
rotation = Math.floor((rotation + delta) / theta + 0.5) * theta;
|
||||||
return rotation;
|
return rotation;
|
||||||
@@ -72,7 +76,11 @@ export function createSnapToZero(opt_tolerance) {
|
|||||||
* @param {number} delta Delta.
|
* @param {number} delta Delta.
|
||||||
* @return {number|undefined} Rotation.
|
* @return {number|undefined} Rotation.
|
||||||
*/
|
*/
|
||||||
function(rotation, delta) {
|
function(rotation, delta, opt_isMoving) {
|
||||||
|
if (opt_isMoving) {
|
||||||
|
return rotation;
|
||||||
|
}
|
||||||
|
|
||||||
if (rotation !== undefined) {
|
if (rotation !== undefined) {
|
||||||
if (Math.abs(rotation + delta) <= tolerance) {
|
if (Math.abs(rotation + delta) <= tolerance) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -365,6 +365,7 @@ describe('ol.View', function() {
|
|||||||
it('applies the current resolution if resolution was originally supplied', function() {
|
it('applies the current resolution if resolution was originally supplied', function() {
|
||||||
const view = new View({
|
const view = new View({
|
||||||
center: [0, 0],
|
center: [0, 0],
|
||||||
|
maxResolution: 2000,
|
||||||
resolution: 1000
|
resolution: 1000
|
||||||
});
|
});
|
||||||
view.setResolution(500);
|
view.setResolution(500);
|
||||||
|
|||||||
Reference in New Issue
Block a user