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.
This commit is contained in:
@@ -29,12 +29,22 @@ export function createExtent(extent, onlyCenter, smooth) {
|
|||||||
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;
|
||||||
const minX = extent[0] + viewWidth / 2;
|
let minX = extent[0] + viewWidth / 2;
|
||||||
const maxX = extent[2] - viewWidth / 2;
|
let maxX = extent[2] - viewWidth / 2;
|
||||||
const minY = extent[1] + viewHeight / 2;
|
let minY = extent[1] + viewHeight / 2;
|
||||||
const maxY = extent[3] - viewHeight / 2;
|
let maxY = extent[3] - viewHeight / 2;
|
||||||
let x = minX > maxX ? (maxX + minX) / 2 : clamp(center[0], minX, maxX);
|
|
||||||
let y = minY > maxY ? (maxY + minY) / 2 : clamp(center[1], minY, maxY);
|
// 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;
|
const ratio = 30 * resolution;
|
||||||
|
|
||||||
// during an interaction, allow some overscroll
|
// during an interaction, allow some overscroll
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ function getViewportClampedResolution(resolution, maxExtent, viewportSize) {
|
|||||||
/**
|
/**
|
||||||
* Returns a modified resolution to be between maxResolution and minResolution while
|
* Returns a modified resolution to be between maxResolution and minResolution while
|
||||||
* still allowing the value to be slightly out of bounds.
|
* still allowing the value to be slightly out of bounds.
|
||||||
|
* Note: the computation is based on the logarithm function (ln):
|
||||||
|
* - at 1, ln(x) is 0
|
||||||
|
* - above 1, ln(x) keeps increasing but at a much slower pace than x
|
||||||
|
* The final result is clamped to prevent getting too far away from bounds.
|
||||||
* @param {number} resolution Resolution.
|
* @param {number} resolution Resolution.
|
||||||
* @param {number} maxResolution Max resolution.
|
* @param {number} maxResolution Max resolution.
|
||||||
* @param {number} minResolution Min resolution.
|
* @param {number} minResolution Min resolution.
|
||||||
@@ -34,13 +38,14 @@ function getViewportClampedResolution(resolution, maxExtent, viewportSize) {
|
|||||||
*/
|
*/
|
||||||
function getSmoothClampedResolution(resolution, maxResolution, minResolution) {
|
function getSmoothClampedResolution(resolution, maxResolution, minResolution) {
|
||||||
let result = Math.min(resolution, maxResolution);
|
let result = Math.min(resolution, maxResolution);
|
||||||
|
const ratio = 50;
|
||||||
|
|
||||||
result *= Math.log(Math.max(1, resolution / maxResolution)) * 0.1 + 1;
|
result *= Math.log(1 + ratio * Math.max(0, resolution / maxResolution - 1)) / ratio + 1;
|
||||||
if (minResolution) {
|
if (minResolution) {
|
||||||
result = Math.max(result, minResolution);
|
result = Math.max(result, minResolution);
|
||||||
result /= Math.log(Math.max(1, minResolution / resolution)) * 0.1 + 1;
|
result /= Math.log(1 + ratio * Math.max(0, minResolution / resolution - 1)) / ratio + 1;
|
||||||
}
|
}
|
||||||
return result;
|
return clamp(result, minResolution / 2, maxResolution * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user