src/gestures/drag.js
/**
* @module gestures
*/
/**
* Move with x fingers (default 1) around on the page.
* Preventing the default browser behavior is a good way to improve feel and working.
* ````
* hammertime.on("drag", function(ev) {
* console.log(ev);
* ev.gesture.preventDefault();
* });
* ````
*
* @class Drag
* @static
*/
/**
* @event drag
* @param {Object} ev
*/
/**
* @event dragstart
* @param {Object} ev
*/
/**
* @event dragend
* @param {Object} ev
*/
/**
* @event drapleft
* @param {Object} ev
*/
/**
* @event dragright
* @param {Object} ev
*/
/**
* @event dragup
* @param {Object} ev
*/
/**
* @event dragdown
* @param {Object} ev
*/
/**
* @param {String} name
*/
(function(name) {
var triggered = false;
function dragGesture(ev, inst) {
var cur = Detection.current;
// max touches
if(inst.options.dragMaxTouches > 0 &&
ev.touches.length > inst.options.dragMaxTouches) {
return;
}
switch(ev.eventType) {
case EVENT_START:
triggered = false;
break;
case EVENT_MOVE:
// when the distance we moved is too small we skip this gesture
// or we can be already in dragging
if(ev.distance < inst.options.dragMinDistance &&
cur.name != name) {
return;
}
var startCenter = cur.startEvent.center;
// we are dragging!
if(cur.name != name) {
cur.name = name;
if(inst.options.dragDistanceCorrection && ev.distance > 0) {
// When a drag is triggered, set the event center to dragMinDistance pixels from the original event center.
// Without this correction, the dragged distance would jumpstart at dragMinDistance pixels instead of at 0.
// It might be useful to save the original start point somewhere
var factor = Math.abs(inst.options.dragMinDistance / ev.distance);
startCenter.pageX += ev.deltaX * factor;
startCenter.pageY += ev.deltaY * factor;
startCenter.clientX += ev.deltaX * factor;
startCenter.clientY += ev.deltaY * factor;
// recalculate event data using new start point
ev = Detection.extendEventData(ev);
}
}
// lock drag to axis?
if(cur.lastEvent.dragLockToAxis ||
( inst.options.dragLockToAxis &&
inst.options.dragLockMinDistance <= ev.distance
)) {
ev.dragLockToAxis = true;
}
// keep direction on the axis that the drag gesture started on
var lastDirection = cur.lastEvent.direction;
if(ev.dragLockToAxis && lastDirection !== ev.direction) {
if(Utils.isVertical(lastDirection)) {
ev.direction = (ev.deltaY < 0) ? DIRECTION_UP : DIRECTION_DOWN;
} else {
ev.direction = (ev.deltaX < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT;
}
}
// first time, trigger dragstart event
if(!triggered) {
inst.trigger(name + 'start', ev);
triggered = true;
}
// trigger events
inst.trigger(name, ev);
inst.trigger(name + ev.direction, ev);
var isVertical = Utils.isVertical(ev.direction);
// block the browser events
if((inst.options.dragBlockVertical && isVertical) ||
(inst.options.dragBlockHorizontal && !isVertical)) {
ev.preventDefault();
}
break;
case EVENT_RELEASE:
if(triggered && ev.changedLength <= inst.options.dragMaxTouches) {
inst.trigger(name + 'end', ev);
triggered = false;
}
break;
case EVENT_END:
triggered = false;
break;
}
}
Hammer.gestures.Drag = {
name: name,
index: 50,
handler: dragGesture,
defaults: {
/**
* minimal movement that have to be made before the drag event gets triggered
* @property dragMinDistance
* @type {Number}
* @default 10
*/
dragMinDistance: 10,
/**
* Set dragDistanceCorrection to true to make the starting point of the drag
* be calculated from where the drag was triggered, not from where the touch started.
* Useful to avoid a jerk-starting drag, which can make fine-adjustments
* through dragging difficult, and be visually unappealing.
* @property dragDistanceCorrection
* @type {Boolean}
* @default true
*/
dragDistanceCorrection: true,
/**
* set 0 for unlimited, but this can conflict with transform
* @property dragMaxTouches
* @type {Number}
* @default 1
*/
dragMaxTouches: 1,
/**
* prevent default browser behavior when dragging occurs
* be careful with it, it makes the element a blocking element
* when you are using the drag gesture, it is a good practice to set this true
* @property dragBlockHorizontal
* @type {Boolean}
* @default false
*/
dragBlockHorizontal: false,
/**
* same as `dragBlockHorizontal`, but for vertical movement
* @property dragBlockVertical
* @type {Boolean}
* @default false
*/
dragBlockVertical: false,
/**
* dragLockToAxis keeps the drag gesture on the axis that it started on,
* It disallows vertical directions if the initial direction was horizontal, and vice versa.
* @property dragLockToAxis
* @type {Boolean}
* @default false
*/
dragLockToAxis: false,
/**
* drag lock only kicks in when distance > dragLockMinDistance
* This way, locking occurs only when the distance has become large enough to reliably determine the direction
* @property dragLockMinDistance
* @type {Number}
* @default 25
*/
dragLockMinDistance: 25
}
};
})('drag');