View / add a 'smoothResolutionConstraint' options
When enabled (true by default), the resolution min/max values will be applied with a smoothing effect for a better user experience.
This commit is contained in:
+14
-9
@@ -123,6 +123,9 @@ import {createMinMaxResolution} from './resolutionconstraint';
|
|||||||
* @property {boolean} [constrainResolution] If true, the view will always
|
* @property {boolean} [constrainResolution] If true, the view will always
|
||||||
* animate to the closest zoom level after an interaction; false means
|
* animate to the closest zoom level after an interaction; false means
|
||||||
* intermediary zoom levels are allowed. Default is false.
|
* intermediary zoom levels are allowed. Default is false.
|
||||||
|
* @property {boolean} [smoothResolutionConstraint] If true, the resolution
|
||||||
|
* min/max values will be applied smoothly, i. e. allow the view to exceed slightly
|
||||||
|
* the given resolution or zoom bounds. Default is true.
|
||||||
* @property {import("./proj.js").ProjectionLike} [projection='EPSG:3857'] The
|
* @property {import("./proj.js").ProjectionLike} [projection='EPSG:3857'] The
|
||||||
* projection. The default is Spherical Mercator.
|
* projection. The default is Spherical Mercator.
|
||||||
* @property {number} [resolution] The initial resolution for the view. The
|
* @property {number} [resolution] The initial resolution for the view. The
|
||||||
@@ -978,8 +981,7 @@ class View extends BaseObject {
|
|||||||
const zoomFactor = this.resolutions_[baseLevel] / this.resolutions_[baseLevel + 1];
|
const zoomFactor = this.resolutions_[baseLevel] / this.resolutions_[baseLevel + 1];
|
||||||
return this.resolutions_[baseLevel] / Math.pow(zoomFactor, clamp(zoom - baseLevel, 0, 1));
|
return this.resolutions_[baseLevel] / Math.pow(zoomFactor, clamp(zoom - baseLevel, 0, 1));
|
||||||
} else {
|
} else {
|
||||||
return clamp(this.maxResolution_ / Math.pow(this.zoomFactor_, zoom - this.minZoom_),
|
return this.maxResolution_ / Math.pow(this.zoomFactor_, zoom - this.minZoom_);
|
||||||
this.minResolution_, this.maxResolution_);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1203,7 +1205,7 @@ class View extends BaseObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the rotation for this view.
|
* Set the rotation for this view using an anchor.
|
||||||
* @param {number} rotation The rotation of the view in radians.
|
* @param {number} rotation The rotation of the view in radians.
|
||||||
* @observable
|
* @observable
|
||||||
* @api
|
* @api
|
||||||
@@ -1214,7 +1216,7 @@ class View extends BaseObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Zoom to a specific zoom level.
|
* Zoom to a specific zoom level using an anchor
|
||||||
* @param {number} zoom Zoom level.
|
* @param {number} zoom Zoom level.
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
@@ -1263,7 +1265,7 @@ class View extends BaseObject {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
resolveConstraints_(opt_duration, opt_resolutionDirection) {
|
resolveConstraints_(opt_duration, opt_resolutionDirection) {
|
||||||
const duration = opt_duration || 200;
|
const duration = opt_duration !== undefined ? opt_duration : 200;
|
||||||
const direction = opt_resolutionDirection || 0;
|
const direction = opt_resolutionDirection || 0;
|
||||||
|
|
||||||
const newRotation = this.constraints_.rotation(this.targetRotation_);
|
const newRotation = this.constraints_.rotation(this.targetRotation_);
|
||||||
@@ -1391,6 +1393,9 @@ export function createResolutionConstraint(options) {
|
|||||||
const zoomFactor = options.zoomFactor !== undefined ?
|
const zoomFactor = options.zoomFactor !== undefined ?
|
||||||
options.zoomFactor : defaultZoomFactor;
|
options.zoomFactor : defaultZoomFactor;
|
||||||
|
|
||||||
|
const smooth =
|
||||||
|
options.smoothResolutionConstraint !== undefined ? options.smoothResolutionConstraint : true;
|
||||||
|
|
||||||
if (options.resolutions !== undefined) {
|
if (options.resolutions !== undefined) {
|
||||||
const resolutions = options.resolutions;
|
const resolutions = options.resolutions;
|
||||||
maxResolution = resolutions[minZoom];
|
maxResolution = resolutions[minZoom];
|
||||||
@@ -1398,10 +1403,10 @@ export function createResolutionConstraint(options) {
|
|||||||
resolutions[maxZoom] : resolutions[resolutions.length - 1];
|
resolutions[maxZoom] : resolutions[resolutions.length - 1];
|
||||||
|
|
||||||
if (options.constrainResolution) {
|
if (options.constrainResolution) {
|
||||||
resolutionConstraint = createSnapToResolutions(resolutions,
|
resolutionConstraint = createSnapToResolutions(resolutions, smooth,
|
||||||
!options.constrainOnlyCenter && options.extent);
|
!options.constrainOnlyCenter && options.extent);
|
||||||
} else {
|
} else {
|
||||||
resolutionConstraint = createMinMaxResolution(maxResolution, minResolution,
|
resolutionConstraint = createMinMaxResolution(maxResolution, minResolution, smooth,
|
||||||
!options.constrainOnlyCenter && options.extent);
|
!options.constrainOnlyCenter && options.extent);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1449,10 +1454,10 @@ export function createResolutionConstraint(options) {
|
|||||||
|
|
||||||
if (options.constrainResolution) {
|
if (options.constrainResolution) {
|
||||||
resolutionConstraint = createSnapToPower(
|
resolutionConstraint = createSnapToPower(
|
||||||
zoomFactor, maxResolution, minResolution,
|
zoomFactor, maxResolution, minResolution, smooth,
|
||||||
!options.constrainOnlyCenter && options.extent);
|
!options.constrainOnlyCenter && options.extent);
|
||||||
} else {
|
} else {
|
||||||
resolutionConstraint = createMinMaxResolution(maxResolution, minResolution,
|
resolutionConstraint = createMinMaxResolution(maxResolution, minResolution, smooth,
|
||||||
!options.constrainOnlyCenter && options.extent);
|
!options.constrainOnlyCenter && options.extent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ export function createExtent(extent, onlyCenter, smooth) {
|
|||||||
const maxX = extent[2] - viewWidth / 2;
|
const maxX = extent[2] - viewWidth / 2;
|
||||||
const minY = extent[1] + viewHeight / 2;
|
const minY = extent[1] + viewHeight / 2;
|
||||||
const maxY = extent[3] - viewHeight / 2;
|
const maxY = extent[3] - viewHeight / 2;
|
||||||
let x = clamp(center[0], minX, maxX);
|
let x = minX > maxX ? (maxX + minX) / 2 : clamp(center[0], minX, maxX);
|
||||||
let y = clamp(center[1], minY, maxY);
|
let y = minY > maxY ? (maxY + minY) / 2 : clamp(center[1], minY, maxY);
|
||||||
let ratio = 30 * resolution;
|
const ratio = 30 * resolution;
|
||||||
|
|
||||||
// during an interaction, allow some overscroll
|
// during an interaction, allow some overscroll
|
||||||
if (opt_isMoving && smooth) {
|
if (opt_isMoving && smooth) {
|
||||||
|
|||||||
@@ -102,13 +102,13 @@ class ZoomSlider extends Control {
|
|||||||
* @type {number|undefined}
|
* @type {number|undefined}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.previousX_;
|
this.startX_;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {number|undefined}
|
* @type {number|undefined}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.previousY_;
|
this.startY_;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The calculated thumb size (border box plus margins). Set when initSlider_
|
* The calculated thumb size (border box plus margins). Set when initSlider_
|
||||||
@@ -234,9 +234,10 @@ class ZoomSlider extends Control {
|
|||||||
*/
|
*/
|
||||||
handleDraggerStart_(event) {
|
handleDraggerStart_(event) {
|
||||||
if (!this.dragging_ && event.originalEvent.target === this.element.firstElementChild) {
|
if (!this.dragging_ && event.originalEvent.target === this.element.firstElementChild) {
|
||||||
|
const element = /** @type {HTMLElement} */ (this.element.firstElementChild);
|
||||||
this.getMap().getView().beginInteraction();
|
this.getMap().getView().beginInteraction();
|
||||||
this.previousX_ = event.clientX;
|
this.startX_ = event.clientX - parseFloat(element.style.left);
|
||||||
this.previousY_ = event.clientY;
|
this.startY_ = event.clientY - parseFloat(element.style.top);
|
||||||
this.dragging_ = true;
|
this.dragging_ = true;
|
||||||
|
|
||||||
if (this.dragListenerKeys_.length === 0) {
|
if (this.dragListenerKeys_.length === 0) {
|
||||||
@@ -260,15 +261,11 @@ class ZoomSlider extends Control {
|
|||||||
*/
|
*/
|
||||||
handleDraggerDrag_(event) {
|
handleDraggerDrag_(event) {
|
||||||
if (this.dragging_) {
|
if (this.dragging_) {
|
||||||
const element = /** @type {HTMLElement} */ (this.element.firstElementChild);
|
const deltaX = event.clientX - this.startX_;
|
||||||
const deltaX = event.clientX - this.previousX_ + parseFloat(element.style.left);
|
const deltaY = event.clientY - this.startY_;
|
||||||
const deltaY = event.clientY - this.previousY_ + parseFloat(element.style.top);
|
|
||||||
const relativePosition = this.getRelativePosition_(deltaX, deltaY);
|
const relativePosition = this.getRelativePosition_(deltaX, deltaY);
|
||||||
this.currentResolution_ = this.getResolutionForPosition_(relativePosition);
|
this.currentResolution_ = this.getResolutionForPosition_(relativePosition);
|
||||||
this.getMap().getView().setResolution(this.currentResolution_);
|
this.getMap().getView().setResolution(this.currentResolution_);
|
||||||
this.setThumbPosition_(this.currentResolution_);
|
|
||||||
this.previousX_ = event.clientX;
|
|
||||||
this.previousY_ = event.clientY;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,18 +279,9 @@ class ZoomSlider extends Control {
|
|||||||
const view = this.getMap().getView();
|
const view = this.getMap().getView();
|
||||||
view.endInteraction();
|
view.endInteraction();
|
||||||
|
|
||||||
const zoom = view.getValidZoomLevel(
|
|
||||||
view.getZoomForResolution(this.currentResolution_));
|
|
||||||
|
|
||||||
view.animate({
|
|
||||||
zoom: zoom,
|
|
||||||
duration: this.duration_,
|
|
||||||
easing: easeOut
|
|
||||||
});
|
|
||||||
|
|
||||||
this.dragging_ = false;
|
this.dragging_ = false;
|
||||||
this.previousX_ = undefined;
|
this.startX_ = undefined;
|
||||||
this.previousY_ = undefined;
|
this.startY_ = undefined;
|
||||||
this.dragListenerKeys_.forEach(unlistenByKey);
|
this.dragListenerKeys_.forEach(unlistenByKey);
|
||||||
this.dragListenerKeys_.length = 0;
|
this.dragListenerKeys_.length = 0;
|
||||||
}
|
}
|
||||||
@@ -360,7 +348,7 @@ class ZoomSlider extends Control {
|
|||||||
*/
|
*/
|
||||||
getPositionForResolution_(res) {
|
getPositionForResolution_(res) {
|
||||||
const fn = this.getMap().getView().getValueForResolutionFunction();
|
const fn = this.getMap().getView().getValueForResolutionFunction();
|
||||||
return 1 - fn(res);
|
return clamp(1 - fn(res), 0, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,10 +367,8 @@ export function render(mapEvent) {
|
|||||||
this.initSlider_();
|
this.initSlider_();
|
||||||
}
|
}
|
||||||
const res = mapEvent.frameState.viewState.resolution;
|
const res = mapEvent.frameState.viewState.resolution;
|
||||||
if (res !== this.currentResolution_) {
|
this.currentResolution_ = res;
|
||||||
this.currentResolution_ = res;
|
this.setThumbPosition_(res);
|
||||||
this.setThumbPosition_(res);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -128,19 +128,12 @@ class MouseWheelZoom extends Interaction {
|
|||||||
*/
|
*/
|
||||||
this.trackpadDeltaPerZoom_ = 300;
|
this.trackpadDeltaPerZoom_ = 300;
|
||||||
|
|
||||||
/**
|
|
||||||
* The zoom factor by which scroll zooming is allowed to exceed the limits.
|
|
||||||
* @private
|
|
||||||
* @type {number}
|
|
||||||
*/
|
|
||||||
this.trackpadZoomBuffer_ = 1.5;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
decrementInteractingHint_() {
|
endInteraction_() {
|
||||||
this.trackpadTimeoutId_ = undefined;
|
this.trackpadTimeoutId_ = undefined;
|
||||||
const view = this.getMap().getView();
|
const view = this.getMap().getView();
|
||||||
view.endInteraction();
|
view.endInteraction();
|
||||||
@@ -211,7 +204,7 @@ class MouseWheelZoom extends Interaction {
|
|||||||
} else {
|
} else {
|
||||||
view.beginInteraction();
|
view.beginInteraction();
|
||||||
}
|
}
|
||||||
this.trackpadTimeoutId_ = setTimeout(this.decrementInteractingHint_.bind(this), this.trackpadEventGap_);
|
this.trackpadTimeoutId_ = setTimeout(this.endInteraction_.bind(this), this.trackpadEventGap_);
|
||||||
view.adjustZoom(-delta / this.trackpadDeltaPerZoom_, this.lastAnchor_);
|
view.adjustZoom(-delta / this.trackpadDeltaPerZoom_, this.lastAnchor_);
|
||||||
this.startTime_ = now;
|
this.startTime_ = now;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -11,24 +11,45 @@ import {getHeight, getWidth} from './extent';
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Returns a modified resolution taking into acocunt the viewport size and maximum
|
||||||
|
* allowed extent.
|
||||||
* @param {number} resolution Resolution
|
* @param {number} resolution Resolution
|
||||||
* @param {import("./extent.js").Extent=} maxExtent Maximum allowed extent.
|
* @param {import("./extent.js").Extent=} maxExtent Maximum allowed extent.
|
||||||
* @param {import("./size.js").Size} viewportSize Viewport size.
|
* @param {import("./size.js").Size} viewportSize Viewport size.
|
||||||
* @return {number} Capped resolution.
|
* @return {number} Capped resolution.
|
||||||
*/
|
*/
|
||||||
function getCappedResolution(resolution, maxExtent, viewportSize) {
|
function getViewportClampedResolution(resolution, maxExtent, viewportSize) {
|
||||||
const xResolution = getWidth(maxExtent) / viewportSize[0];
|
const xResolution = getWidth(maxExtent) / viewportSize[0];
|
||||||
const yResolution = getHeight(maxExtent) / viewportSize[1];
|
const yResolution = getHeight(maxExtent) / viewportSize[1];
|
||||||
return Math.min(resolution, Math.min(xResolution, yResolution));
|
return Math.min(resolution, Math.min(xResolution, yResolution));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a modified resolution to be between maxResolution and minResolution while
|
||||||
|
* still allowing the value to be slightly out of bounds.
|
||||||
|
* @param {number} resolution Resolution.
|
||||||
|
* @param {number} maxResolution Max resolution.
|
||||||
|
* @param {number} minResolution Min resolution.
|
||||||
|
* @return {number} Smoothed resolution.
|
||||||
|
*/
|
||||||
|
function getSmoothClampedResolution(resolution, maxResolution, minResolution) {
|
||||||
|
let result = Math.min(resolution, maxResolution);
|
||||||
|
|
||||||
|
result *= Math.log(Math.max(1, resolution / maxResolution)) * 0.1 + 1;
|
||||||
|
if (minResolution) {
|
||||||
|
result = Math.max(result, minResolution);
|
||||||
|
result /= Math.log(Math.max(1, minResolution / resolution)) * 0.1 + 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Array<number>} resolutions Resolutions.
|
* @param {Array<number>} resolutions Resolutions.
|
||||||
|
* @param {boolean=} opt_smooth If true, the view will be able to slightly exceed resolution limits. Default: true.
|
||||||
* @param {import("./extent.js").Extent=} opt_maxExtent Maximum allowed extent.
|
* @param {import("./extent.js").Extent=} opt_maxExtent Maximum allowed extent.
|
||||||
* @return {Type} Zoom function.
|
* @return {Type} Zoom function.
|
||||||
*/
|
*/
|
||||||
export function createSnapToResolutions(resolutions, opt_maxExtent) {
|
export function createSnapToResolutions(resolutions, opt_smooth, opt_maxExtent) {
|
||||||
return (
|
return (
|
||||||
/**
|
/**
|
||||||
* @param {number|undefined} resolution Resolution.
|
* @param {number|undefined} resolution Resolution.
|
||||||
@@ -39,16 +60,23 @@ export function createSnapToResolutions(resolutions, opt_maxExtent) {
|
|||||||
*/
|
*/
|
||||||
function(resolution, direction, size, opt_isMoving) {
|
function(resolution, direction, size, opt_isMoving) {
|
||||||
if (resolution !== undefined) {
|
if (resolution !== undefined) {
|
||||||
const cappedRes = opt_maxExtent ? getCappedResolution(resolution, opt_maxExtent, size) : resolution;
|
const maxResolution = resolutions[0];
|
||||||
|
const minResolution = resolutions[resolutions.length - 1];
|
||||||
|
const cappedMaxRes = opt_maxExtent ?
|
||||||
|
getViewportClampedResolution(maxResolution, opt_maxExtent, size) :
|
||||||
|
maxResolution;
|
||||||
|
|
||||||
// during interacting or animating, allow intermediary values
|
// during interacting or animating, allow intermediary values
|
||||||
if (opt_isMoving) {
|
if (opt_isMoving) {
|
||||||
const maxResolution = resolutions[0];
|
const smooth = opt_smooth !== undefined ? opt_smooth : true;
|
||||||
const minResolution = resolutions[resolutions.length - 1];
|
if (!smooth) {
|
||||||
return clamp(cappedRes, minResolution, maxResolution);
|
return clamp(resolution, minResolution, cappedMaxRes);
|
||||||
|
}
|
||||||
|
return getSmoothClampedResolution(resolution, cappedMaxRes, minResolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
let z = Math.floor(linearFindNearest(resolutions, cappedRes, direction));
|
const capped = Math.min(cappedMaxRes, resolution);
|
||||||
|
const z = Math.floor(linearFindNearest(resolutions, capped, direction));
|
||||||
return resolutions[z];
|
return resolutions[z];
|
||||||
} else {
|
} else {
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -62,10 +90,11 @@ export function createSnapToResolutions(resolutions, opt_maxExtent) {
|
|||||||
* @param {number} power Power.
|
* @param {number} power Power.
|
||||||
* @param {number} maxResolution Maximum resolution.
|
* @param {number} maxResolution Maximum resolution.
|
||||||
* @param {number=} opt_minResolution Minimum resolution.
|
* @param {number=} opt_minResolution Minimum resolution.
|
||||||
|
* @param {boolean=} opt_smooth If true, the view will be able to slightly exceed resolution limits. Default: true.
|
||||||
* @param {import("./extent.js").Extent=} opt_maxExtent Maximum allowed extent.
|
* @param {import("./extent.js").Extent=} opt_maxExtent Maximum allowed extent.
|
||||||
* @return {Type} Zoom function.
|
* @return {Type} Zoom function.
|
||||||
*/
|
*/
|
||||||
export function createSnapToPower(power, maxResolution, opt_minResolution, opt_maxExtent) {
|
export function createSnapToPower(power, maxResolution, opt_minResolution, opt_smooth, opt_maxExtent) {
|
||||||
return (
|
return (
|
||||||
/**
|
/**
|
||||||
* @param {number|undefined} resolution Resolution.
|
* @param {number|undefined} resolution Resolution.
|
||||||
@@ -76,20 +105,26 @@ export function createSnapToPower(power, maxResolution, opt_minResolution, opt_m
|
|||||||
*/
|
*/
|
||||||
function(resolution, direction, size, opt_isMoving) {
|
function(resolution, direction, size, opt_isMoving) {
|
||||||
if (resolution !== undefined) {
|
if (resolution !== undefined) {
|
||||||
const cappedRes = opt_maxExtent ? getCappedResolution(resolution, opt_maxExtent, size) : resolution;
|
const cappedMaxRes = opt_maxExtent ?
|
||||||
|
getViewportClampedResolution(maxResolution, opt_maxExtent, size) :
|
||||||
|
maxResolution;
|
||||||
|
const minResolution = opt_minResolution !== undefined ? opt_minResolution : 0;
|
||||||
|
|
||||||
// during interacting or animating, allow intermediary values
|
// during interacting or animating, allow intermediary values
|
||||||
if (opt_isMoving) {
|
if (opt_isMoving) {
|
||||||
return opt_minResolution !== undefined ? Math.max(opt_minResolution, cappedRes) : cappedRes;
|
const smooth = opt_smooth !== undefined ? opt_smooth : true;
|
||||||
|
if (!smooth) {
|
||||||
|
return clamp(resolution, minResolution, cappedMaxRes);
|
||||||
|
}
|
||||||
|
return getSmoothClampedResolution(resolution, cappedMaxRes, minResolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
const offset = -direction * (0.5 - 1e-9) + 0.5;
|
const offset = -direction * (0.5 - 1e-9) + 0.5;
|
||||||
|
const capped = Math.min(cappedMaxRes, resolution);
|
||||||
const zoomLevel = Math.floor(
|
const zoomLevel = Math.floor(
|
||||||
Math.log(maxResolution / cappedRes) / Math.log(power) + offset);
|
Math.log(maxResolution / capped) / Math.log(power) + offset);
|
||||||
let newResolution = maxResolution / Math.pow(power, zoomLevel);
|
let newResolution = maxResolution / Math.pow(power, zoomLevel);
|
||||||
return opt_minResolution !== undefined ?
|
return clamp(newResolution, minResolution, cappedMaxRes);
|
||||||
clamp(newResolution, opt_minResolution, maxResolution) :
|
|
||||||
Math.min(maxResolution, newResolution);
|
|
||||||
} else {
|
} else {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@@ -99,10 +134,11 @@ export function createSnapToPower(power, maxResolution, opt_minResolution, opt_m
|
|||||||
/**
|
/**
|
||||||
* @param {number} maxResolution Max resolution.
|
* @param {number} maxResolution Max resolution.
|
||||||
* @param {number} minResolution Min resolution.
|
* @param {number} minResolution Min resolution.
|
||||||
|
* @param {boolean=} opt_smooth If true, the view will be able to slightly exceed resolution limits. Default: true.
|
||||||
* @param {import("./extent.js").Extent=} opt_maxExtent Maximum allowed extent.
|
* @param {import("./extent.js").Extent=} opt_maxExtent Maximum allowed extent.
|
||||||
* @return {Type} Zoom function.
|
* @return {Type} Zoom function.
|
||||||
*/
|
*/
|
||||||
export function createMinMaxResolution(maxResolution, minResolution, opt_maxExtent) {
|
export function createMinMaxResolution(maxResolution, minResolution, opt_smooth, opt_maxExtent) {
|
||||||
return (
|
return (
|
||||||
/**
|
/**
|
||||||
* @param {number|undefined} resolution Resolution.
|
* @param {number|undefined} resolution Resolution.
|
||||||
@@ -113,8 +149,15 @@ export function createMinMaxResolution(maxResolution, minResolution, opt_maxExte
|
|||||||
*/
|
*/
|
||||||
function(resolution, direction, size, opt_isMoving) {
|
function(resolution, direction, size, opt_isMoving) {
|
||||||
if (resolution !== undefined) {
|
if (resolution !== undefined) {
|
||||||
const cappedRes = opt_maxExtent ? getCappedResolution(resolution, opt_maxExtent, size) : resolution;
|
const cappedMaxRes = opt_maxExtent ?
|
||||||
return clamp(cappedRes, minResolution, maxResolution);
|
getViewportClampedResolution(maxResolution, opt_maxExtent, size) :
|
||||||
|
maxResolution;
|
||||||
|
const smooth = opt_smooth !== undefined ? opt_smooth : true;
|
||||||
|
|
||||||
|
if (!smooth || !opt_isMoving) {
|
||||||
|
return clamp(resolution, minResolution, cappedMaxRes);
|
||||||
|
}
|
||||||
|
return getSmoothClampedResolution(resolution, cappedMaxRes, minResolution);
|
||||||
} else {
|
} else {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {createSnapToResolutions, createSnapToPower} from '../../../src/ol/resolutionconstraint.js';
|
import {createSnapToResolutions, createSnapToPower} from '../../../src/ol/resolutionconstraint.js';
|
||||||
|
import {createMinMaxResolution} from '../../../src/ol/resolutionconstraint';
|
||||||
|
|
||||||
|
|
||||||
describe('ol.resolutionconstraint', function() {
|
describe('ol.resolutionconstraint', function() {
|
||||||
@@ -238,4 +239,98 @@ describe('ol.resolutionconstraint', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('SnapToPower smooth constraint', function() {
|
||||||
|
|
||||||
|
describe('snap to power, smooth constraint on', function() {
|
||||||
|
it('returns expected resolution value', function() {
|
||||||
|
let resolutionConstraint = createSnapToPower(2, 128, 16, true);
|
||||||
|
|
||||||
|
expect(resolutionConstraint(150, 0, [100, 100], true)).to.be.greaterThan(128);
|
||||||
|
expect(resolutionConstraint(150, 0, [100, 100], true)).to.be.lessThan(150);
|
||||||
|
expect(resolutionConstraint(130, 0, [100, 100], true)).to.be.greaterThan(128);
|
||||||
|
expect(resolutionConstraint(130, 0, [100, 100], true)).to.be.lessThan(130);
|
||||||
|
expect(resolutionConstraint(128, 0, [100, 100], true)).to.eql(128);
|
||||||
|
expect(resolutionConstraint(16, 0, [100, 100], true)).to.eql(16);
|
||||||
|
expect(resolutionConstraint(15, 0, [100, 100], true)).to.be.greaterThan(15);
|
||||||
|
expect(resolutionConstraint(15, 0, [100, 100], true)).to.be.lessThan(16);
|
||||||
|
expect(resolutionConstraint(10, 0, [100, 100], true)).to.be.greaterThan(10);
|
||||||
|
expect(resolutionConstraint(10, 0, [100, 100], true)).to.be.lessThan(16);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('snap to power, smooth constraint off', function() {
|
||||||
|
it('returns expected resolution value', function() {
|
||||||
|
let resolutionConstraint = createSnapToPower(2, 128, 16, false);
|
||||||
|
|
||||||
|
expect(resolutionConstraint(150, 0, [100, 100], true)).to.eql(128);
|
||||||
|
expect(resolutionConstraint(130, 0, [100, 100], true)).to.eql(128);
|
||||||
|
expect(resolutionConstraint(128, 0, [100, 100], true)).to.eql(128);
|
||||||
|
expect(resolutionConstraint(16, 0, [100, 100], true)).to.eql(16);
|
||||||
|
expect(resolutionConstraint(15, 0, [100, 100], true)).to.eql(16);
|
||||||
|
expect(resolutionConstraint(10, 0, [100, 100], true)).to.eql(16);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('snap to resolutions, smooth constraint on', function() {
|
||||||
|
it('returns expected resolution value', function() {
|
||||||
|
let resolutionConstraint = createSnapToResolutions([128, 64, 32, 16], true);
|
||||||
|
|
||||||
|
expect(resolutionConstraint(150, 0, [100, 100], true)).to.be.greaterThan(128);
|
||||||
|
expect(resolutionConstraint(150, 0, [100, 100], true)).to.be.lessThan(150);
|
||||||
|
expect(resolutionConstraint(130, 0, [100, 100], true)).to.be.greaterThan(128);
|
||||||
|
expect(resolutionConstraint(130, 0, [100, 100], true)).to.be.lessThan(130);
|
||||||
|
expect(resolutionConstraint(128, 0, [100, 100], true)).to.eql(128);
|
||||||
|
expect(resolutionConstraint(16, 0, [100, 100], true)).to.eql(16);
|
||||||
|
expect(resolutionConstraint(15, 0, [100, 100], true)).to.be.greaterThan(15);
|
||||||
|
expect(resolutionConstraint(15, 0, [100, 100], true)).to.be.lessThan(16);
|
||||||
|
expect(resolutionConstraint(10, 0, [100, 100], true)).to.be.greaterThan(10);
|
||||||
|
expect(resolutionConstraint(10, 0, [100, 100], true)).to.be.lessThan(16);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('snap to resolutions, smooth constraint off', function() {
|
||||||
|
it('returns expected resolution value', function() {
|
||||||
|
let resolutionConstraint = createSnapToResolutions([128, 64, 32, 16], false);
|
||||||
|
|
||||||
|
expect(resolutionConstraint(150, 0, [100, 100], true)).to.eql(128);
|
||||||
|
expect(resolutionConstraint(130, 0, [100, 100], true)).to.eql(128);
|
||||||
|
expect(resolutionConstraint(128, 0, [100, 100], true)).to.eql(128);
|
||||||
|
expect(resolutionConstraint(16, 0, [100, 100], true)).to.eql(16);
|
||||||
|
expect(resolutionConstraint(15, 0, [100, 100], true)).to.eql(16);
|
||||||
|
expect(resolutionConstraint(10, 0, [100, 100], true)).to.eql(16);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('min/max, smooth constraint on', function() {
|
||||||
|
it('returns expected resolution value', function() {
|
||||||
|
let resolutionConstraint = createMinMaxResolution(128, 16, true);
|
||||||
|
|
||||||
|
expect(resolutionConstraint(150, 0, [100, 100], true)).to.be.greaterThan(128);
|
||||||
|
expect(resolutionConstraint(150, 0, [100, 100], true)).to.be.lessThan(150);
|
||||||
|
expect(resolutionConstraint(130, 0, [100, 100], true)).to.be.greaterThan(128);
|
||||||
|
expect(resolutionConstraint(130, 0, [100, 100], true)).to.be.lessThan(130);
|
||||||
|
expect(resolutionConstraint(128, 0, [100, 100], true)).to.eql(128);
|
||||||
|
expect(resolutionConstraint(16, 0, [100, 100], true)).to.eql(16);
|
||||||
|
expect(resolutionConstraint(15, 0, [100, 100], true)).to.be.greaterThan(15);
|
||||||
|
expect(resolutionConstraint(15, 0, [100, 100], true)).to.be.lessThan(16);
|
||||||
|
expect(resolutionConstraint(10, 0, [100, 100], true)).to.be.greaterThan(10);
|
||||||
|
expect(resolutionConstraint(10, 0, [100, 100], true)).to.be.lessThan(16);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('min/max, smooth constraint off', function() {
|
||||||
|
it('returns expected resolution value', function() {
|
||||||
|
let resolutionConstraint = createMinMaxResolution(128, 16, false);
|
||||||
|
|
||||||
|
expect(resolutionConstraint(150, 0, [100, 100], true)).to.eql(128);
|
||||||
|
expect(resolutionConstraint(130, 0, [100, 100], true)).to.eql(128);
|
||||||
|
expect(resolutionConstraint(128, 0, [100, 100], true)).to.eql(128);
|
||||||
|
expect(resolutionConstraint(16, 0, [100, 100], true)).to.eql(16);
|
||||||
|
expect(resolutionConstraint(15, 0, [100, 100], true)).to.eql(16);
|
||||||
|
expect(resolutionConstraint(10, 0, [100, 100], true)).to.eql(16);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user