hammerjs
Version:
A javascript library for multi-touch gestures
136 lines (116 loc) • 4.92 kB
JavaScript
/**
* Drag
* Move with x fingers (default 1) around on the page. Blocking the scrolling when
* moving left and right is a good practice. When all the drag events are blocking
* you disable scrolling on that area.
* @events drag, drapleft, dragright, dragup, dragdown
*/
Hammer.gestures.Drag = {
name : 'drag',
index : 50,
defaults : {
drag_min_distance : 10,
// Set correct_for_drag_min_distance 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.
correct_for_drag_min_distance: true,
// set 0 for unlimited, but this can conflict with transform
drag_max_touches : 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
drag_block_horizontal : false,
drag_block_vertical : false,
// drag_lock_to_axis keeps the drag gesture on the axis that it started on,
// It disallows vertical directions if the initial direction was horizontal, and vice versa.
drag_lock_to_axis : false,
// drag lock only kicks in when distance > drag_lock_min_distance
// This way, locking occurs only when the distance has become large enough to reliably determine the direction
drag_lock_min_distance : 25
},
triggered: false,
handler : function dragGesture(ev, inst) {
var cur = Detection.current;
// current gesture isnt drag, but dragged is true
// this means an other gesture is busy. now call dragend
if(cur.name != this.name && this.triggered) {
inst.trigger(this.name + 'end', ev);
this.triggered = false;
return;
}
// max touches
if(inst.options.drag_max_touches > 0 &&
ev.touches.length > inst.options.drag_max_touches) {
return;
}
switch(ev.eventType) {
case EVENT_START:
this.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.drag_min_distance &&
cur.name != this.name) {
return;
}
var startCenter = cur.startEvent.center;
// we are dragging!
if(cur.name != this.name) {
cur.name = this.name;
if(inst.options.correct_for_drag_min_distance && ev.distance > 0) {
// When a drag is triggered, set the event center to drag_min_distance pixels from the original event center.
// Without this correction, the dragged distance would jumpstart at drag_min_distance pixels instead of at 0.
// It might be useful to save the original start point somewhere
var factor = Math.abs(inst.options.drag_min_distance / 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.drag_locked_to_axis ||
( inst.options.drag_lock_to_axis &&
inst.options.drag_lock_min_distance <= ev.distance
)) {
ev.drag_locked_to_axis = true;
}
var last_direction = cur.lastEvent.direction;
if(ev.drag_locked_to_axis && last_direction !== ev.direction) {
// keep direction on the axis that the drag gesture started on
if(Utils.isVertical(last_direction)) {
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(!this.triggered) {
inst.trigger(this.name + 'start', ev);
this.triggered = true;
}
// trigger events
inst.trigger(this.name, ev);
inst.trigger(this.name + ev.direction, ev);
var is_vertical = Utils.isVertical(ev.direction);
// block the browser events
if((inst.options.drag_block_vertical && is_vertical) ||
(inst.options.drag_block_horizontal && !is_vertical)) {
ev.preventDefault();
}
break;
case EVENT_END:
// trigger dragend
if(this.triggered) {
inst.trigger(this.name + 'end', ev);
}
this.triggered = false;
break;
}
}
};