Handle center constraint properly
This commit is contained in:
117
src/ol/View.js
117
src/ol/View.js
@@ -1116,10 +1116,11 @@ class View extends BaseObject {
|
|||||||
/**
|
/**
|
||||||
* Returns the size of the viewport minus padding.
|
* Returns the size of the viewport minus padding.
|
||||||
* @private
|
* @private
|
||||||
|
* @param {number=} opt_rotation Take into account the rotation of the viewport when giving the size
|
||||||
* @return {import("./size.js").Size} Viewport size reduced by the padding.
|
* @return {import("./size.js").Size} Viewport size reduced by the padding.
|
||||||
*/
|
*/
|
||||||
getViewportSizeMinusPadding_() {
|
getViewportSizeMinusPadding_(opt_rotation) {
|
||||||
let size = this.getViewportSize_();
|
let size = this.getViewportSize_(opt_rotation);
|
||||||
const padding = this.padding;
|
const padding = this.padding;
|
||||||
if (padding) {
|
if (padding) {
|
||||||
size = [
|
size = [
|
||||||
@@ -1134,18 +1135,21 @@ class View extends BaseObject {
|
|||||||
* @return {State} View state.
|
* @return {State} View state.
|
||||||
*/
|
*/
|
||||||
getState() {
|
getState() {
|
||||||
|
const projection = this.getProjection();
|
||||||
|
const resolution = /** @type {number} */ (this.getResolution());
|
||||||
|
const rotation = this.getRotation();
|
||||||
let center = /** @type {import("./coordinate.js").Coordinate} */ (this.getCenterInternal());
|
let center = /** @type {import("./coordinate.js").Coordinate} */ (this.getCenterInternal());
|
||||||
const padding = this.padding;
|
const padding = this.padding;
|
||||||
if (padding) {
|
if (padding) {
|
||||||
const reducedSize = this.getViewportSizeMinusPadding_();
|
const reducedSize = this.getViewportSizeMinusPadding_();
|
||||||
center = this.calculateShiftedCenter(center, this.getViewportSize_(), [
|
center = calculateCenterOn(
|
||||||
reducedSize[0] / 2 + padding[3],
|
center,
|
||||||
reducedSize[1] / 2 + padding[0],
|
this.getViewportSize_(),
|
||||||
]);
|
[reducedSize[0] / 2 + padding[3], reducedSize[1] / 2 + padding[0]],
|
||||||
|
resolution,
|
||||||
|
rotation
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const projection = this.getProjection();
|
|
||||||
const resolution = /** @type {number} */ (this.getResolution());
|
|
||||||
const rotation = this.getRotation();
|
|
||||||
return {
|
return {
|
||||||
center: center.slice(0),
|
center: center.slice(0),
|
||||||
projection: projection !== undefined ? projection : null,
|
projection: projection !== undefined ? projection : null,
|
||||||
@@ -1371,33 +1375,42 @@ class View extends BaseObject {
|
|||||||
*/
|
*/
|
||||||
centerOnInternal(coordinate, size, position) {
|
centerOnInternal(coordinate, size, position) {
|
||||||
this.setCenterInternal(
|
this.setCenterInternal(
|
||||||
this.calculateShiftedCenter(coordinate, size, position)
|
calculateCenterOn(
|
||||||
|
coordinate,
|
||||||
|
size,
|
||||||
|
position,
|
||||||
|
this.getResolution(),
|
||||||
|
this.getRotation()
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import("./coordinate.js").Coordinate} coordinate Coordinate.
|
* Calculates the shift between map and viewport center.
|
||||||
* @param {import("./size.js").Size} size Box pixel size.
|
* @param {import("./coordinate.js").Coordinate} center Center.
|
||||||
* @param {import("./pixel.js").Pixel} position Position on the view to center on.
|
* @param {number} resolution Resolution.
|
||||||
* @return {import("./coordinate.js").Coordinate} Shifted center.
|
* @param {number} rotation Rotation.
|
||||||
|
* @param {import("./size.js").Size} size Size.
|
||||||
|
* @return {Array<number>|undefined} Center shift.
|
||||||
*/
|
*/
|
||||||
calculateShiftedCenter(coordinate, size, position) {
|
calculateCenterShift(center, resolution, rotation, size) {
|
||||||
// calculate rotated position
|
let centerShift;
|
||||||
const rotation = this.getRotation();
|
const padding = this.padding;
|
||||||
const cosAngle = Math.cos(-rotation);
|
if (padding && center) {
|
||||||
let sinAngle = Math.sin(-rotation);
|
const reducedSize = this.getViewportSizeMinusPadding_(-rotation);
|
||||||
let rotX = coordinate[0] * cosAngle - coordinate[1] * sinAngle;
|
const shiftedCenter = calculateCenterOn(
|
||||||
let rotY = coordinate[1] * cosAngle + coordinate[0] * sinAngle;
|
center,
|
||||||
const resolution = this.getResolution();
|
size,
|
||||||
rotX += (size[0] / 2 - position[0]) * resolution;
|
[reducedSize[0] / 2 + padding[3], reducedSize[1] / 2 + padding[0]],
|
||||||
rotY += (position[1] - size[1] / 2) * resolution;
|
resolution,
|
||||||
|
rotation
|
||||||
// go back to original angle
|
);
|
||||||
sinAngle = -sinAngle; // go back to original rotation
|
centerShift = [
|
||||||
const centerX = rotX * cosAngle - rotY * sinAngle;
|
center[0] - shiftedCenter[0],
|
||||||
const centerY = rotY * cosAngle + rotX * sinAngle;
|
center[1] - shiftedCenter[1],
|
||||||
|
];
|
||||||
return [centerX, centerY];
|
}
|
||||||
|
return centerShift;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1600,7 +1613,13 @@ class View extends BaseObject {
|
|||||||
this.targetCenter_,
|
this.targetCenter_,
|
||||||
newResolution,
|
newResolution,
|
||||||
size,
|
size,
|
||||||
isMoving
|
isMoving,
|
||||||
|
this.calculateCenterShift(
|
||||||
|
this.targetCenter_,
|
||||||
|
newResolution,
|
||||||
|
newRotation,
|
||||||
|
size
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (this.get(ViewProperty.ROTATION) !== newRotation) {
|
if (this.get(ViewProperty.ROTATION) !== newRotation) {
|
||||||
@@ -1645,7 +1664,14 @@ class View extends BaseObject {
|
|||||||
const newCenter = this.constraints_.center(
|
const newCenter = this.constraints_.center(
|
||||||
this.targetCenter_,
|
this.targetCenter_,
|
||||||
newResolution,
|
newResolution,
|
||||||
size
|
size,
|
||||||
|
false,
|
||||||
|
this.calculateCenterShift(
|
||||||
|
this.targetCenter_,
|
||||||
|
newResolution,
|
||||||
|
newRotation,
|
||||||
|
size
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (duration === 0 && !this.cancelAnchor_) {
|
if (duration === 0 && !this.cancelAnchor_) {
|
||||||
@@ -1986,4 +2012,29 @@ export function isNoopAnimation(animation) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import("./coordinate.js").Coordinate} coordinate Coordinate.
|
||||||
|
* @param {import("./size.js").Size} size Box pixel size.
|
||||||
|
* @param {import("./pixel.js").Pixel} position Position on the view to center on.
|
||||||
|
* @param {number} resolution Resolution.
|
||||||
|
* @param {number} rotation Rotation.
|
||||||
|
* @return {import("./coordinate.js").Coordinate} Shifted center.
|
||||||
|
*/
|
||||||
|
function calculateCenterOn(coordinate, size, position, resolution, rotation) {
|
||||||
|
// calculate rotated position
|
||||||
|
const cosAngle = Math.cos(-rotation);
|
||||||
|
let sinAngle = Math.sin(-rotation);
|
||||||
|
let rotX = coordinate[0] * cosAngle - coordinate[1] * sinAngle;
|
||||||
|
let rotY = coordinate[1] * cosAngle + coordinate[0] * sinAngle;
|
||||||
|
rotX += (size[0] / 2 - position[0]) * resolution;
|
||||||
|
rotY += (position[1] - size[1] / 2) * resolution;
|
||||||
|
|
||||||
|
// go back to original angle
|
||||||
|
sinAngle = -sinAngle; // go back to original rotation
|
||||||
|
const centerX = rotX * cosAngle - rotY * sinAngle;
|
||||||
|
const centerY = rotY * cosAngle + rotX * sinAngle;
|
||||||
|
|
||||||
|
return [centerX, centerY];
|
||||||
|
}
|
||||||
|
|
||||||
export default View;
|
export default View;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import {clamp} from './math.js';
|
import {clamp} from './math.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {function((import("./coordinate.js").Coordinate|undefined), number, import("./size.js").Size, boolean=): (import("./coordinate.js").Coordinate|undefined)} Type
|
* @typedef {function((import("./coordinate.js").Coordinate|undefined), number, import("./size.js").Size, boolean=, Array<number>=): (import("./coordinate.js").Coordinate|undefined)} Type
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,16 +21,19 @@ export function createExtent(extent, onlyCenter, smooth) {
|
|||||||
* @param {number} resolution Resolution.
|
* @param {number} resolution Resolution.
|
||||||
* @param {import("./size.js").Size} size Viewport size; unused if `onlyCenter` was specified.
|
* @param {import("./size.js").Size} size Viewport size; unused if `onlyCenter` was specified.
|
||||||
* @param {boolean=} opt_isMoving True if an interaction or animation is in progress.
|
* @param {boolean=} opt_isMoving True if an interaction or animation is in progress.
|
||||||
|
* @param {Array<number>=} opt_centerShift Shift between map center and viewport center.
|
||||||
* @return {import("./coordinate.js").Coordinate|undefined} Center.
|
* @return {import("./coordinate.js").Coordinate|undefined} Center.
|
||||||
*/
|
*/
|
||||||
function (center, resolution, size, opt_isMoving) {
|
function (center, resolution, size, opt_isMoving, opt_centerShift) {
|
||||||
if (center) {
|
if (center) {
|
||||||
const viewWidth = onlyCenter ? 0 : size[0] * resolution;
|
const viewWidth = onlyCenter ? 0 : size[0] * resolution;
|
||||||
const viewHeight = onlyCenter ? 0 : size[1] * resolution;
|
const viewHeight = onlyCenter ? 0 : size[1] * resolution;
|
||||||
let minX = extent[0] + viewWidth / 2;
|
const shiftX = opt_centerShift ? opt_centerShift[0] : 0;
|
||||||
let maxX = extent[2] - viewWidth / 2;
|
const shiftY = opt_centerShift ? opt_centerShift[1] : 0;
|
||||||
let minY = extent[1] + viewHeight / 2;
|
let minX = extent[0] + viewWidth / 2 + shiftX;
|
||||||
let maxY = extent[3] - viewHeight / 2;
|
let maxX = extent[2] - viewWidth / 2 + shiftX;
|
||||||
|
let minY = extent[1] + viewHeight / 2 + shiftY;
|
||||||
|
let maxY = extent[3] - viewHeight / 2 + shiftY;
|
||||||
|
|
||||||
// note: when zooming out of bounds, min and max values for x and y may
|
// note: when zooming out of bounds, min and max values for x and y may
|
||||||
// end up inverted (min > max); this has to be accounted for
|
// end up inverted (min > max); this has to be accounted for
|
||||||
|
|||||||
Reference in New Issue
Block a user