Swipe gestures

This commit is contained in:
Max Lynch
2013-08-26 19:09:06 -05:00
parent 90ea2fd684
commit 2db29fb35b
5 changed files with 234 additions and 10 deletions

View File

@ -16,6 +16,7 @@
<a href="#" class="button button-success">Swipe me!</a>
<div id="event-log"></div>
</div>
<script src="../../js/framework/framework-utils.js"></script>
<script src="../../js/framework/framework-gestures.js"></script>
<script src="../../js/framework/framework-events.js"></script>
<script src="events.js"></script>

View File

@ -19,3 +19,51 @@ window.FM.on('touch', function(e) {
event: e
});
});
window.FM.on('release', function(e) {
console.log('GOT RELEASE', e);
logEvent({
type: 'release',
event: e
});
});
window.FM.on('swipe', function(e) {
console.log('GOT SWIPE', e);
logEvent({
type: 'swipe',
event: e
});
e.target.classList.add('swipeleft');
});
window.FM.on('swiperight', function(e) {
console.log('GOT SWIPE RIGHT', e);
logEvent({
type: 'swiperight',
event: e
});
e.target.classList.add('swiperight');
});
window.FM.on('swipeleft', function(e) {
console.log('GOT SWIPE LEFT', e);
logEvent({
type: 'swipeleft',
event: e
});
e.target.classList.add('swipeleft');
});
window.FM.on('swipeup', function(e) {
console.log('GOT SWIPE UP', e);
logEvent({
type: 'swipeup',
event: e
});
});
window.FM.on('swipedown', function(e) {
console.log('GOT SWIPE DOWN', e);
logEvent({
type: 'swipedown',
event: e
});
});

View File

@ -53,7 +53,7 @@
*/
handleTouchStart: function(e) {
console.log("EVENT: touchstart", e);
framework.GestureController.detectGesture(e);
framework.GestureController.startGesture(e);
},
/**

View File

@ -2,7 +2,7 @@
* Simple gesture controllers with some common gestures that emit
* gesture events.
*
* Much adapted from github.com/EightMedia/Hammer.js
* Much adapted from github.com/EightMedia/Hammer.js - thanks!
*/
(function(window, document, framework) {
// Gesture support
@ -55,27 +55,180 @@
}
};
// A swipe-left gesture that emits the 'swipeleft' event when a left swipe
// is performed
framework.Gesture.SwipeLeft = {
// The gesture is over, trigger a release event
framework.Gesture.Release = {
handle: function(e) {
if(e.type === 'touchend') {
framework.EventController.trigger('release', {
cancelable: true,
bubbles: true
});
}
}
};
// A swipe gesture that emits the 'swipe' event when a left swipe happens
framework.Gesture.Swipe = {
swipe_velocity: 0.7,
handle: function(e) {
if(e.type == 'touchend') {
if(e.velocityX > this.swipe_velocity ||
e.velocityY > this.swipe_velocity) {
// trigger swipe events, both a general swipe,
// and a directional swipe
framework.EventController.trigger('swipe', {
gesture: e,
cancelable: true,
bubbles: true
});
framework.EventController.trigger('swipe' + e.direction, {
gesture: e,
cancelable: true,
bubbles: true
});
}
}
}
};
framework.GestureController = {
gestures: [
framework.Gesture.Touch,
framework.Gesture.Tap
framework.Gesture.Tap,
framework.Gesture.Swipe
],
_annotateGestureEvent: function(e) {
// If this doesn't have touches, we need to grab the last set that did
var touches = e.touches;
if((!touches || !touches.length) && this._lastMoveEvent) {
touches = this._lastMoveEvent.touches;
}
e.center = this.getCenter(touches);
var startEv = this.currentGesture.startEvent;
var delta_time = e.timeStamp - startEv.timeStamp;
var delta_x = e.center.pageX - startEv.center.pageX;
var delta_y = e.center.pageY - startEv.center.pageY;
var velocity = this.getVelocity(delta_time, delta_x, delta_y);
framework.Utils.extend(e, {
touches : touches,
deltaTime : delta_time,
deltaX : delta_x,
deltaY : delta_y,
velocityX : velocity.x,
velocityY : velocity.y,
distance : this.getDistance(startEv.center, e.center),
angle : this.getAngle(startEv.center, e.center),
//interimAngle : this.current.lastEvent && Hammer.utils.getAngle(this.current.lastEvent.center, e.center),
direction : this.getDirection(startEv.center, e.center),
//interimDirection: this.current.lastEvent && Hammer.utils.getDirection(this.current.lastEvent.center, e.center),
scale : this.getScale(startEv.touches, touches),
rotation : this.getRotation(startEv.touches, touches),
startEvent : startEv
});
return e;
},
_getFakeEvent: function(e) {
return {
center : this.getCenter(e.touches),
timeStamp : new Date().getTime(),
target : e.target,
touches : e.touches,
eventType : e.type,
srcEvent : e,
/*
// prevent the browser default actions
// mostly used to disable scrolling of the browser
preventDefault: function() {
if(this.srcEvent.preventManipulation) {
this.srcEvent.preventManipulation();
}
if(this.srcEvent.preventDefault) {
this.srcEvent.preventDefault();
}
},
*/
/**
* stop bubbling the event up to its parents
*/
stopPropagation: function() {
this.srcEvent.stopPropagation();
},
//immediately stop gesture detection
//might be useful after a swipe was detected
//@return {*}
stopDetect: function() {
return Hammer.detection.stopDetect();
}
};
},
startGesture: function(e) {
console.log('START GESTURE');
// We only want to process one gesture at a time
if(this.currentGesture) {
return;
}
e = this._getFakeEvent(e);
this.currentGesture = e;
this.currentGesture.startEvent = framework.Utils.extend({}, e);
if((e.touches && e.touches.length) || !this._lastMoveEvent) {
this._lastMoveEvent = e;
}
this.detectGesture(e);
},
detectGesture: function(e) {
var i;
if(e.touches && e.touches.length) {
this._lastMoveEvent = e;
}
var eventData = this._annotateGestureEvent(e);
console.log("Event velocity:", eventData.velocityX, eventData.velocityY);
for(i = 0; i < this.gestures.length; i++) {
if(this.gestures[i].handle(e)) {
console.log('GESTURECONTROLLER: Gesture handled');
if(this.gestures[i].handle(eventData) == false) {
console.log('GESTURECONTROLLER: Gesture handled and stopped.');
this.endGesture(eventData);
return;
}
}
if(this.currentGesture) {
// Store this event so we can access it again later
this.currentGesture.lastEvent = eventData;
}
// It's over!
if(e.type === 'touchend' || e.type === 'touchcancel') {
this.endGesture(eventData);
}
},
endGesture: function(e) {
this.currentGesture = null;
this._lastMoveEvent = null;
},
/**
@ -155,10 +308,10 @@
y = Math.abs(touch1.pageY - touch2.pageY);
if(x >= y) {
return touch1.pageX - touch2.pageX > 0 ? Hammer.DIRECTION_LEFT : Hammer.DIRECTION_RIGHT;
return touch1.pageX - touch2.pageX > 0 ? 'left' : 'right';
}
else {
return touch1.pageY - touch2.pageY > 0 ? Hammer.DIRECTION_UP : Hammer.DIRECTION_DOWN;
return touch1.pageY - touch2.pageY > 0 ? 'up': 'down';
}
},

View File

@ -0,0 +1,22 @@
(function(window, document, framework) {
framework.Utils = {
/**
* extend method,
* also used for cloning when dest is an empty object
* @param {Object} dest
* @param {Object} src
* @parm {Boolean} merge do a merge
* @returns {Object} dest
*/
extend: function extend(dest, src, merge) {
for (var key in src) {
if(dest[key] !== undefined && merge) {
continue;
}
dest[key] = src[key];
}
return dest;
},
}
})(this, document, FM = this.FM || {});