Files
openlayers/src/ol/centerconstraint.js
Olivier Guyot 447266cbe8 Better smoothing of resolution and center constraints
Previously the formula for the resolution constraint allowed going way past
the minimum zoom.
Also adjusted the center constraint to avoid a zigzag effect when going out
of resolution bounds.
2019-03-04 10:14:06 +01:00

74 lines
2.5 KiB
JavaScript

/**
* @module ol/centerconstraint
*/
import {clamp} from './math.js';
/**
* @typedef {function((import("./coordinate.js").Coordinate|undefined), number, import("./size.js").Size, boolean=): (import("./coordinate.js").Coordinate|undefined)} Type
*/
/**
* @param {import("./extent.js").Extent} extent Extent.
* @param {boolean} onlyCenter If true, the constraint will only apply to the view center.
* @param {boolean} smooth If true, the view will be able to go slightly out of the given extent
* (only during interaction and animation).
* @return {Type} The constraint.
*/
export function createExtent(extent, onlyCenter, smooth) {
return (
/**
* @param {import("./coordinate.js").Coordinate|undefined} center Center.
* @param {number} resolution Resolution.
* @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.
* @return {import("./coordinate.js").Coordinate|undefined} Center.
*/
function(center, resolution, size, opt_isMoving) {
if (center) {
const viewWidth = onlyCenter ? 0 : size[0] * resolution;
const viewHeight = onlyCenter ? 0 : size[1] * resolution;
let minX = extent[0] + viewWidth / 2;
let maxX = extent[2] - viewWidth / 2;
let minY = extent[1] + viewHeight / 2;
let maxY = extent[3] - viewHeight / 2;
// 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
if (minX > maxX) {
minX = maxX = (maxX + minX) / 2;
}
if (minY > maxY) {
minY = maxY = (maxY + minY) / 2;
}
let x = clamp(center[0], minX, maxX);
let y = clamp(center[1], minY, maxY);
const ratio = 30 * resolution;
// during an interaction, allow some overscroll
if (opt_isMoving && smooth) {
x += -ratio * Math.log(1 + Math.max(0, minX - center[0]) / ratio) +
ratio * Math.log(1 + Math.max(0, center[0] - maxX) / ratio);
y += -ratio * Math.log(1 + Math.max(0, minY - center[1]) / ratio) +
ratio * Math.log(1 + Math.max(0, center[1] - maxY) / ratio);
}
return [x, y];
} else {
return undefined;
}
}
);
}
/**
* @param {import("./coordinate.js").Coordinate=} center Center.
* @return {import("./coordinate.js").Coordinate|undefined} Center.
*/
export function none(center) {
return center;
}