Add support for kinetic effect while dragging.

Only dragpan interaction is supported for now.

The kinetic effect use the maths below (thx @twpayne):

Rate of decay (number, must be negative) = α
Minimum velocity (pixels/millisecond) = v_min
Initial velocity (pixels/millisecond) = v₀

Velocity at time t (pixels/millisecond) =
    α⋅t
v₀⋅ℯ

Distance travelled at time t (pixels) =
   ⎛ α⋅t    ⎞
v₀⋅⎝ℯ    - 1⎠
─────────────
      α

Duration of animation (milliseconds) =
   ⎛v_min⎞
log⎜─────⎟
   ⎝  v₀ ⎠
──────────
    α

Total distance travelled (pixels) =
-v₀ + v_min
───────────
     α

Easing function =
   ⎛ α⋅duration⋅t    ⎞
v₀⋅⎝ℯ             - 1⎠
──────────────────────
     -v₀ + v_min
This commit is contained in:
Bruno Binet
2013-01-28 17:33:15 +01:00
parent 47fbdb53e2
commit 8a9738d755
2 changed files with 182 additions and 3 deletions

View File

@@ -7,6 +7,7 @@ goog.require('ol.Coordinate');
goog.require('ol.MapBrowserEvent');
goog.require('ol.View2D');
goog.require('ol.ViewHint');
goog.require('ol.animation');
goog.require('ol.interaction.ConditionType');
goog.require('ol.interaction.Drag');
@@ -16,8 +17,9 @@ goog.require('ol.interaction.Drag');
* @constructor
* @extends {ol.interaction.Drag}
* @param {ol.interaction.ConditionType} condition Condition.
* @param {ol.Kinetic=} opt_kinetic Kinetic object.
*/
ol.interaction.DragPan = function(condition) {
ol.interaction.DragPan = function(condition, opt_kinetic) {
goog.base(this);
@@ -27,6 +29,12 @@ ol.interaction.DragPan = function(condition) {
*/
this.condition_ = condition;
/**
* @private
* @type {ol.Kinetic|undefined}
*/
this.kinetic_ = opt_kinetic;
};
goog.inherits(ol.interaction.DragPan, ol.interaction.Drag);
@@ -35,6 +43,9 @@ goog.inherits(ol.interaction.DragPan, ol.interaction.Drag);
* @inheritDoc
*/
ol.interaction.DragPan.prototype.handleDrag = function(mapBrowserEvent) {
if (this.kinetic_) {
this.kinetic_.update(mapBrowserEvent.browserEvent);
}
var map = mapBrowserEvent.map;
// FIXME works for View2D only
var view = map.getView();
@@ -55,9 +66,31 @@ ol.interaction.DragPan.prototype.handleDrag = function(mapBrowserEvent) {
* @inheritDoc
*/
ol.interaction.DragPan.prototype.handleDragEnd = function(mapBrowserEvent) {
// FIXME works for View2D only
var map = mapBrowserEvent.map;
map.requestRenderFrame();
map.getView().setHint(ol.ViewHint.PANNING, -1);
var view = map.getView();
view.setHint(ol.ViewHint.PANNING, -1);
if (this.kinetic_ && this.kinetic_.end()) {
var distance = this.kinetic_.getDistance();
var angle = this.kinetic_.getAngle();
var center = view.getCenter();
var kineticPanFrom = ol.animation.createPanFrom({
source: center,
duration: this.kinetic_.getDuration(),
easing: this.kinetic_.getEasingFn()
});
map.addPreRenderFunction(kineticPanFrom);
var centerpx = map.getPixelFromCoordinate(center);
var destpx = new ol.Pixel(
centerpx.x - distance * Math.cos(angle),
centerpx.y - distance * Math.sin(angle));
var dest = map.getCoordinateFromPixel(destpx);
view.setCenter(dest);
}
};
@@ -67,6 +100,9 @@ ol.interaction.DragPan.prototype.handleDragEnd = function(mapBrowserEvent) {
ol.interaction.DragPan.prototype.handleDragStart = function(mapBrowserEvent) {
var browserEvent = mapBrowserEvent.browserEvent;
if (this.condition_(browserEvent)) {
if (this.kinetic_) {
this.kinetic_.begin(browserEvent);
}
var map = mapBrowserEvent.map;
map.requestRenderFrame();
map.getView().setHint(ol.ViewHint.PANNING, 1);