Merge pull request #473 from elemoine/value-resolution
Exponential scaling to ZoomSlider
This commit is contained in:
@@ -5,7 +5,6 @@
|
||||
goog.provide('ol.control.ZoomSlider');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.events');
|
||||
@@ -19,6 +18,12 @@ goog.require('ol.control.Control');
|
||||
goog.require('ol.css');
|
||||
|
||||
|
||||
/**
|
||||
* @define {number} Animation duration.
|
||||
*/
|
||||
ol.control.ZOOMSLIDER_ANIMATION_DURATION = 200;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
@@ -26,38 +31,6 @@ goog.require('ol.css');
|
||||
* @param {ol.control.ZoomSliderOptions} options Zoom slider options.
|
||||
*/
|
||||
ol.control.ZoomSlider = function(options) {
|
||||
// FIXME these should be read out from a map if not given, and only then
|
||||
// fallback to the constants if they weren't defined on the map.
|
||||
/**
|
||||
* The minimum resolution that one can set with this control.
|
||||
*
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.maxResolution_ = goog.isDef(options.maxResolution) ?
|
||||
options.maxResolution : ol.control.ZoomSlider.DEFAULT_MAX_RESOLUTION;
|
||||
|
||||
/**
|
||||
* The maximum resolution that one can set with this control.
|
||||
*
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.minResolution_ = goog.isDef(options.minResolution) ?
|
||||
options.minResolution : ol.control.ZoomSlider.DEFAULT_MIN_RESOLUTION;
|
||||
|
||||
goog.asserts.assert(
|
||||
this.minResolution_ < this.maxResolution_,
|
||||
'minResolution must be smaller than maxResolution.'
|
||||
);
|
||||
|
||||
/**
|
||||
* The range of resolutions we are handling in this slider.
|
||||
*
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.range_ = this.maxResolution_ - this.minResolution_;
|
||||
|
||||
/**
|
||||
* Will hold the current resolution of the view.
|
||||
@@ -127,34 +100,17 @@ ol.control.ZoomSlider.CSS_CLASS_THUMB =
|
||||
ol.control.ZoomSlider.CSS_CLASS_CONTAINER + '-thumb';
|
||||
|
||||
|
||||
/**
|
||||
* The default value for minResolution_ when the control isn't instanciated with
|
||||
* an explicit value. The default value is the resolution of the standard OSM
|
||||
* tiles at zoomlevel 18.
|
||||
*
|
||||
* @const {number}
|
||||
*/
|
||||
ol.control.ZoomSlider.DEFAULT_MIN_RESOLUTION = 0.5971642833948135;
|
||||
|
||||
|
||||
/**
|
||||
* The default value for maxResolution_ when the control isn't instanciated with
|
||||
* an explicit value. The default value is the resolution of the standard OSM
|
||||
* tiles at zoomlevel 0.
|
||||
*
|
||||
* @const {number}
|
||||
*/
|
||||
ol.control.ZoomSlider.DEFAULT_MAX_RESOLUTION = 156543.0339;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.control.ZoomSlider.prototype.setMap = function(map) {
|
||||
goog.base(this, 'setMap', map);
|
||||
this.currentResolution_ = map.getView().getResolution();
|
||||
this.initSlider_();
|
||||
this.positionThumbForResolution_(this.currentResolution_);
|
||||
var resolution = map.getView().getView2D().getResolution();
|
||||
if (goog.isDef(resolution)) {
|
||||
this.currentResolution_ = resolution;
|
||||
this.positionThumbForResolution_(resolution);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -259,13 +215,14 @@ ol.control.ZoomSlider.prototype.amountDragged_ = function(e) {
|
||||
* been dragged from its minimum.
|
||||
*
|
||||
* @param {number} amount The amount the thumb has been dragged.
|
||||
* @return {number} a resolution between this.minResolution_ and
|
||||
* this.maxResolution_.
|
||||
* @return {number} The corresponding resolution.
|
||||
* @private
|
||||
*/
|
||||
ol.control.ZoomSlider.prototype.resolutionForAmount_ = function(amount) {
|
||||
var saneAmount = goog.math.clamp(amount, 0, 1);
|
||||
return this.minResolution_ + this.range_ * saneAmount;
|
||||
// FIXME do we really need this affine transform?
|
||||
amount = (goog.math.clamp(amount, 0, 1) - 1) * -1;
|
||||
var fn = this.getMap().getView().getView2D().getResolutionForValueFunction();
|
||||
return fn(amount);
|
||||
};
|
||||
|
||||
|
||||
@@ -274,12 +231,14 @@ ol.control.ZoomSlider.prototype.resolutionForAmount_ = function(amount) {
|
||||
* given resolution.
|
||||
*
|
||||
* @param {number} res The resolution to get the amount for.
|
||||
* @return {number} an amount between 0 and 1.
|
||||
* @return {number} The corresponding value (between 0 and 1).
|
||||
* @private
|
||||
*/
|
||||
ol.control.ZoomSlider.prototype.amountForResolution_ = function(res) {
|
||||
var saneRes = goog.math.clamp(res, this.minResolution_, this.maxResolution_);
|
||||
return (saneRes - this.minResolution_) / this.range_;
|
||||
var fn = this.getMap().getView().getView2D().getValueForResolutionFunction();
|
||||
var value = fn(res);
|
||||
// FIXME do we really need this affine transform?
|
||||
return (value - 1) * -1;
|
||||
};
|
||||
|
||||
|
||||
@@ -295,11 +254,14 @@ ol.control.ZoomSlider.prototype.handleSliderChange_ = function(e) {
|
||||
var map = this.getMap(),
|
||||
amountDragged = this.amountDragged_(e),
|
||||
res = this.resolutionForAmount_(amountDragged);
|
||||
goog.asserts.assert(res >= this.minResolution_ && res <= this.maxResolution_,
|
||||
'calculated new resolution is in allowed bounds.');
|
||||
if (res !== this.currentResolution_) {
|
||||
this.currentResolution_ = res;
|
||||
map.getView().setResolution(res);
|
||||
if (e.type === goog.fx.Dragger.EventType.DRAG) {
|
||||
if (res !== this.currentResolution_) {
|
||||
this.currentResolution_ = res;
|
||||
map.getView().getView2D().zoomWithoutConstraints(map, res);
|
||||
}
|
||||
} else {
|
||||
map.getView().getView2D().zoom(map, this.currentResolution_, undefined,
|
||||
ol.control.ZOOMSLIDER_ANIMATION_DURATION);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ goog.require('ol.IView3D');
|
||||
goog.require('ol.Projection');
|
||||
goog.require('ol.ResolutionConstraint');
|
||||
goog.require('ol.RotationConstraint');
|
||||
goog.require('ol.RotationConstraintType');
|
||||
goog.require('ol.Size');
|
||||
goog.require('ol.View');
|
||||
goog.require('ol.animation');
|
||||
@@ -64,11 +65,29 @@ ol.View2D = function(opt_options) {
|
||||
values[ol.View2DProperty.ROTATION] = options.rotation;
|
||||
this.setValues(values);
|
||||
|
||||
var parts = ol.View2D.createResolutionConstraint_(options);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.maxResolution_ = parts[1];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.minResolution_ = parts[2];
|
||||
|
||||
var resolutionConstraint = parts[0];
|
||||
var rotationConstraint = ol.View2D.createRotationConstraint_(options);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Constraints}
|
||||
*/
|
||||
this.constraints_ = ol.View2D.createConstraints_(options);
|
||||
this.constraints_ = new ol.Constraints(resolutionConstraint,
|
||||
rotationConstraint);
|
||||
|
||||
};
|
||||
goog.inherits(ol.View2D, ol.View);
|
||||
@@ -141,6 +160,26 @@ ol.View2D.prototype.getResolutionForExtent = function(extent, size) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return a function that returns a value between 0 and 1 for a
|
||||
* resolution. Exponential scaling is assumed.
|
||||
* @param {number=} opt_power Power.
|
||||
* @return {function(number): number} Resolution for value function.
|
||||
*/
|
||||
ol.View2D.prototype.getResolutionForValueFunction = function(opt_power) {
|
||||
var power = opt_power || 2;
|
||||
var maxResolution = this.maxResolution_;
|
||||
var minResolution = this.minResolution_;
|
||||
var max = Math.log(maxResolution / minResolution) / Math.log(power);
|
||||
return function(value) {
|
||||
var resolution = maxResolution / Math.pow(power, value * max);
|
||||
goog.asserts.assert(resolution >= minResolution &&
|
||||
resolution <= maxResolution);
|
||||
return resolution;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Map rotation.
|
||||
*/
|
||||
@@ -154,6 +193,25 @@ goog.exportProperty(
|
||||
ol.View2D.prototype.getRotation);
|
||||
|
||||
|
||||
/**
|
||||
* Return a function that returns a resolution for a value between
|
||||
* 0 and 1. Exponential scaling is assumed.
|
||||
* @param {number=} opt_power Power.
|
||||
* @return {function(number): number} Value for resolution function.
|
||||
*/
|
||||
ol.View2D.prototype.getValueForResolutionFunction = function(opt_power) {
|
||||
var power = opt_power || 2;
|
||||
var maxResolution = this.maxResolution_;
|
||||
var minResolution = this.minResolution_;
|
||||
var max = Math.log(maxResolution / minResolution) / Math.log(power);
|
||||
return function(resolution) {
|
||||
var value = (Math.log(maxResolution / resolution) / Math.log(power)) / max;
|
||||
goog.asserts.assert(value >= 0 && value <= 1);
|
||||
return value;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@@ -420,15 +478,21 @@ ol.View2D.prototype.zoomWithoutConstraints =
|
||||
/**
|
||||
* @private
|
||||
* @param {ol.View2DOptions} options View2D options.
|
||||
* @return {ol.Constraints} Constraints.
|
||||
* @return {Array} Array of three elements: the resolution constraint,
|
||||
* maxResolution, and minResolution.
|
||||
*/
|
||||
ol.View2D.createConstraints_ = function(options) {
|
||||
ol.View2D.createResolutionConstraint_ = function(options) {
|
||||
var resolutionConstraint;
|
||||
var maxResolution;
|
||||
var minResolution;
|
||||
if (goog.isDef(options.resolutions)) {
|
||||
var resolutions = options.resolutions;
|
||||
maxResolution = resolutions[0];
|
||||
minResolution = resolutions[resolutions.length - 1];
|
||||
resolutionConstraint = ol.ResolutionConstraint.createSnapToResolutions(
|
||||
options.resolutions);
|
||||
resolutions);
|
||||
} else {
|
||||
var maxResolution, numZoomLevels, zoomFactor;
|
||||
var numZoomLevels, zoomFactor;
|
||||
if (goog.isDef(options.maxResolution) &&
|
||||
goog.isDef(options.numZoomLevels) &&
|
||||
goog.isDef(options.zoomFactor)) {
|
||||
@@ -444,10 +508,20 @@ ol.View2D.createConstraints_ = function(options) {
|
||||
numZoomLevels = 29;
|
||||
zoomFactor = 2;
|
||||
}
|
||||
minResolution = maxResolution / Math.pow(zoomFactor, numZoomLevels - 1);
|
||||
resolutionConstraint = ol.ResolutionConstraint.createSnapToPower(
|
||||
zoomFactor, maxResolution, numZoomLevels - 1);
|
||||
}
|
||||
// FIXME rotation constraint is not configurable at the moment
|
||||
var rotationConstraint = ol.RotationConstraint.createSnapToZero();
|
||||
return new ol.Constraints(resolutionConstraint, rotationConstraint);
|
||||
return [resolutionConstraint, maxResolution, minResolution];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {ol.View2DOptions} options View2D options.
|
||||
* @return {ol.RotationConstraintType} Rotation constraint.
|
||||
*/
|
||||
ol.View2D.createRotationConstraint_ = function(options) {
|
||||
// FIXME rotation constraint is not configurable at the moment
|
||||
return ol.RotationConstraint.createSnapToZero();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user