support for swipe and pinch gestures #48
This commit is contained in:
commit
4f08e2aeb0
199
js/reveal.js
199
js/reveal.js
|
@ -53,7 +53,18 @@ var Reveal = (function(){
|
||||||
mouseWheelTimeout = 0,
|
mouseWheelTimeout = 0,
|
||||||
|
|
||||||
// Delays updates to the URL due to a Chrome thumbnailer bug
|
// Delays updates to the URL due to a Chrome thumbnailer bug
|
||||||
writeURLTimeout = 0;
|
writeURLTimeout = 0,
|
||||||
|
|
||||||
|
// Holds information about the currently ongoing touch input
|
||||||
|
touch = {
|
||||||
|
startX: 0,
|
||||||
|
startY: 0,
|
||||||
|
startSpan: 0,
|
||||||
|
startCount: 0,
|
||||||
|
handled: false,
|
||||||
|
threshold: 40
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts up the slideshow by applying configuration
|
* Starts up the slideshow by applying configuration
|
||||||
|
@ -79,14 +90,7 @@ var Reveal = (function(){
|
||||||
dom.controlsUp = document.querySelector( '#reveal .controls .up' );
|
dom.controlsUp = document.querySelector( '#reveal .controls .up' );
|
||||||
dom.controlsDown = document.querySelector( '#reveal .controls .down' );
|
dom.controlsDown = document.querySelector( '#reveal .controls .down' );
|
||||||
|
|
||||||
// Bind all view events
|
addEventListeners();
|
||||||
document.addEventListener( 'keydown', onDocumentKeyDown, false );
|
|
||||||
document.addEventListener( 'touchstart', onDocumentTouchStart, false );
|
|
||||||
window.addEventListener( 'hashchange', onWindowHashChange, false );
|
|
||||||
dom.controlsLeft.addEventListener( 'click', preventAndForward( navigateLeft ), false );
|
|
||||||
dom.controlsRight.addEventListener( 'click', preventAndForward( navigateRight ), false );
|
|
||||||
dom.controlsUp.addEventListener( 'click', preventAndForward( navigateUp ), false );
|
|
||||||
dom.controlsDown.addEventListener( 'click', preventAndForward( navigateDown ), false );
|
|
||||||
|
|
||||||
// Copy options over to our config object
|
// Copy options over to our config object
|
||||||
extend( config, options );
|
extend( config, options );
|
||||||
|
@ -135,6 +139,33 @@ var Reveal = (function(){
|
||||||
window.addEventListener( 'load', removeAddressBar, false );
|
window.addEventListener( 'load', removeAddressBar, false );
|
||||||
window.addEventListener( 'orientationchange', removeAddressBar, false );
|
window.addEventListener( 'orientationchange', removeAddressBar, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function addEventListeners() {
|
||||||
|
document.addEventListener( 'keydown', onDocumentKeyDown, false );
|
||||||
|
document.addEventListener( 'touchstart', onDocumentTouchStart, false );
|
||||||
|
document.addEventListener( 'touchmove', onDocumentTouchMove, false );
|
||||||
|
document.addEventListener( 'touchend', onDocumentTouchEnd, false );
|
||||||
|
window.addEventListener( 'hashchange', onWindowHashChange, false );
|
||||||
|
|
||||||
|
dom.controlsLeft.addEventListener( 'click', preventAndForward( navigateLeft ), false );
|
||||||
|
dom.controlsRight.addEventListener( 'click', preventAndForward( navigateRight ), false );
|
||||||
|
dom.controlsUp.addEventListener( 'click', preventAndForward( navigateUp ), false );
|
||||||
|
dom.controlsDown.addEventListener( 'click', preventAndForward( navigateDown ), false );
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeEventListeners() {
|
||||||
|
document.removeEventListener( 'keydown', onDocumentKeyDown, false );
|
||||||
|
document.removeEventListener( 'touchstart', onDocumentTouchStart, false );
|
||||||
|
document.removeEventListener( 'touchmove', onDocumentTouchMove, false );
|
||||||
|
document.removeEventListener( 'touchend', onDocumentTouchEnd, false );
|
||||||
|
window.removeEventListener( 'hashchange', onWindowHashChange, false );
|
||||||
|
|
||||||
|
dom.controlsLeft.removeEventListener( 'click', preventAndForward( navigateLeft ), false );
|
||||||
|
dom.controlsRight.removeEventListener( 'click', preventAndForward( navigateRight ), false );
|
||||||
|
dom.controlsUp.removeEventListener( 'click', preventAndForward( navigateUp ), false );
|
||||||
|
dom.controlsDown.removeEventListener( 'click', preventAndForward( navigateDown ), false );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -147,6 +178,13 @@ var Reveal = (function(){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function distanceBetween( a, b ) {
|
||||||
|
var dx = a.x - b.x,
|
||||||
|
dy = a.y - b.y;
|
||||||
|
|
||||||
|
return Math.sqrt( dx*dx + dy*dy );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prevents an events defaults behavior calls the
|
* Prevents an events defaults behavior calls the
|
||||||
* specified delegate.
|
* specified delegate.
|
||||||
|
@ -224,54 +262,98 @@ var Reveal = (function(){
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for the document level 'touchstart' event.
|
* Handler for the document level 'touchstart' event,
|
||||||
*
|
* enables support for swipe and pinch gestures.
|
||||||
* This enables very basic tap interaction for touch
|
|
||||||
* devices. Added mainly for performance testing of 3D
|
|
||||||
* transforms on iOS but was so happily surprised with
|
|
||||||
* how smoothly it runs so I left it in here. Apple +1
|
|
||||||
*
|
|
||||||
* @param {Object} event
|
|
||||||
*/
|
*/
|
||||||
function onDocumentTouchStart( event ) {
|
function onDocumentTouchStart( event ) {
|
||||||
// We're only interested in one point taps
|
touch.startX = event.touches[0].clientX;
|
||||||
if (event.touches.length === 1) {
|
touch.startY = event.touches[0].clientY;
|
||||||
// Never prevent taps on anchors and images
|
touch.startCount = event.touches.length;
|
||||||
if( event.target.tagName.toLowerCase() === 'a' || event.target.tagName.toLowerCase() === 'img' ) {
|
|
||||||
return;
|
// If there's two touches we need to memorize the distance
|
||||||
|
// between those two points to detect pinching
|
||||||
|
if( event.touches.length === 2 ) {
|
||||||
|
touch.startSpan = distanceBetween( {
|
||||||
|
x: event.touches[1].clientX,
|
||||||
|
y: event.touches[1].clientY
|
||||||
|
}, {
|
||||||
|
x: touch.startX,
|
||||||
|
y: touch.startY
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for the document level 'touchmove' event.
|
||||||
|
*/
|
||||||
|
function onDocumentTouchMove( event ) {
|
||||||
|
// Each touch should only trigger one action
|
||||||
|
if( !touch.handled ) {
|
||||||
|
var currentX = event.touches[0].clientX;
|
||||||
|
var currentY = event.touches[0].clientY;
|
||||||
|
|
||||||
|
// If the touch started off with two points and still has
|
||||||
|
// two active touches; test for the pinch gesture
|
||||||
|
if( event.touches.length === 2 && touch.startCount === 2 ) {
|
||||||
|
|
||||||
|
// The current distance in pixels between the two touch points
|
||||||
|
var currentSpan = distanceBetween( {
|
||||||
|
x: event.touches[1].clientX,
|
||||||
|
y: event.touches[1].clientY
|
||||||
|
}, {
|
||||||
|
x: touch.startX,
|
||||||
|
y: touch.startY
|
||||||
|
} );
|
||||||
|
|
||||||
|
// If the span is larger than the desire amount we've got
|
||||||
|
// ourselves a pinch
|
||||||
|
if( Math.abs( touch.startSpan - currentSpan ) > touch.threshold ) {
|
||||||
|
touch.handled = true;
|
||||||
|
|
||||||
|
if( currentSpan < touch.startSpan ) {
|
||||||
|
activateOverview();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
deactivateOverview();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// There was only one touch point, look for a swipe
|
||||||
|
else if( event.touches.length === 1 ) {
|
||||||
|
var deltaX = currentX - touch.startX,
|
||||||
|
deltaY = currentY - touch.startY;
|
||||||
|
|
||||||
|
if( deltaX > touch.threshold && Math.abs( deltaX ) > Math.abs( deltaY ) ) {
|
||||||
|
touch.handled = true;
|
||||||
|
navigateLeft();
|
||||||
|
}
|
||||||
|
else if( deltaX < -touch.threshold && Math.abs( deltaX ) > Math.abs( deltaY ) ) {
|
||||||
|
touch.handled = true;
|
||||||
|
navigateRight();
|
||||||
|
}
|
||||||
|
else if( deltaY > touch.threshold ) {
|
||||||
|
touch.handled = true;
|
||||||
|
navigateUp();
|
||||||
|
}
|
||||||
|
else if( deltaY < -touch.threshold ) {
|
||||||
|
touch.handled = true;
|
||||||
|
navigateDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
var point = {
|
|
||||||
x: event.touches[0].clientX,
|
|
||||||
y: event.touches[0].clientY
|
|
||||||
};
|
|
||||||
|
|
||||||
// Define the extent of the areas that may be tapped
|
|
||||||
// to navigate
|
|
||||||
var wt = window.innerWidth * 0.3;
|
|
||||||
var ht = window.innerHeight * 0.3;
|
|
||||||
|
|
||||||
if( point.x < wt ) {
|
|
||||||
navigateLeft();
|
|
||||||
}
|
|
||||||
else if( point.x > window.innerWidth - wt ) {
|
|
||||||
navigateRight();
|
|
||||||
}
|
|
||||||
else if( point.y < ht ) {
|
|
||||||
navigateUp();
|
|
||||||
}
|
|
||||||
else if( point.y > window.innerHeight - ht ) {
|
|
||||||
navigateDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
slide();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for the document level 'touchend' event.
|
||||||
|
*/
|
||||||
|
function onDocumentTouchEnd( event ) {
|
||||||
|
touch.handled = false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles mouse wheel scrolling, throttled to avoid
|
* Handles mouse wheel scrolling, throttled to avoid
|
||||||
|
@ -326,6 +408,7 @@ var Reveal = (function(){
|
||||||
* can't be improved.
|
* can't be improved.
|
||||||
*/
|
*/
|
||||||
function activateOverview() {
|
function activateOverview() {
|
||||||
|
|
||||||
dom.wrapper.classList.add( 'overview' );
|
dom.wrapper.classList.add( 'overview' );
|
||||||
|
|
||||||
var horizontalSlides = Array.prototype.slice.call( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
|
var horizontalSlides = Array.prototype.slice.call( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
|
||||||
|
@ -341,12 +424,12 @@ var Reveal = (function(){
|
||||||
hslide.style.msTransform = htransform;
|
hslide.style.msTransform = htransform;
|
||||||
hslide.style.OTransform = htransform;
|
hslide.style.OTransform = htransform;
|
||||||
hslide.style.transform = htransform;
|
hslide.style.transform = htransform;
|
||||||
|
|
||||||
if( !hslide.classList.contains( 'stack' ) ) {
|
if( !hslide.classList.contains( 'stack' ) ) {
|
||||||
// Navigate to this slide on click
|
// Navigate to this slide on click
|
||||||
hslide.addEventListener( 'click', onOverviewSlideClicked, true );
|
hslide.addEventListener( 'click', onOverviewSlideClicked, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
var verticalSlides = Array.prototype.slice.call( hslide.querySelectorAll( 'section' ) );
|
var verticalSlides = Array.prototype.slice.call( hslide.querySelectorAll( 'section' ) );
|
||||||
|
|
||||||
for( var j = 0, len2 = verticalSlides.length; j < len2; j++ ) {
|
for( var j = 0, len2 = verticalSlides.length; j < len2; j++ ) {
|
||||||
|
@ -365,6 +448,7 @@ var Reveal = (function(){
|
||||||
// Navigate to this slide on click
|
// Navigate to this slide on click
|
||||||
vslide.addEventListener( 'click', onOverviewSlideClicked, true );
|
vslide.addEventListener( 'click', onOverviewSlideClicked, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -786,6 +870,18 @@ var Reveal = (function(){
|
||||||
availableRoutes().down ? navigateDown() : navigateRight();
|
availableRoutes().down ? navigateDown() : navigateRight();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles the slide overview mode on and off.
|
||||||
|
*/
|
||||||
|
function toggleOverview() {
|
||||||
|
if( overviewIsActive() ) {
|
||||||
|
deactivateOverview();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
activateOverview();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Expose some methods publicly
|
// Expose some methods publicly
|
||||||
return {
|
return {
|
||||||
|
@ -795,6 +891,7 @@ var Reveal = (function(){
|
||||||
navigateRight: navigateRight,
|
navigateRight: navigateRight,
|
||||||
navigateUp: navigateUp,
|
navigateUp: navigateUp,
|
||||||
navigateDown: navigateDown,
|
navigateDown: navigateDown,
|
||||||
|
toggleOverview: toggleOverview,
|
||||||
|
|
||||||
// Forward event binding to the reveal DOM element
|
// Forward event binding to the reveal DOM element
|
||||||
addEventListener: function( type, listener, useCapture ) {
|
addEventListener: function( type, listener, useCapture ) {
|
||||||
|
|
94
js/reveal.min.js
vendored
94
js/reveal.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user