functional playback control for auto sliding

This commit is contained in:
Hakim El Hattab 2013-10-13 14:36:27 -04:00
parent 356a1cf3b7
commit abf33e55b0
4 changed files with 107 additions and 44 deletions

View file

@ -1561,6 +1561,7 @@ body {
left: 15px; left: 15px;
bottom: 15px; bottom: 15px;
z-index: 30; z-index: 30;
cursor: pointer;
} }

2
css/reveal.min.css vendored

File diff suppressed because one or more lines are too long

View file

@ -114,9 +114,6 @@ var Reveal = (function(){
// Flags if reveal.js is loaded (has dispatched the 'ready' event) // Flags if reveal.js is loaded (has dispatched the 'ready' event)
loaded = false, loaded = false,
// The current auto-slide duration
autoSlide = 0,
// The horizontal and vertical index of the currently active slide // The horizontal and vertical index of the currently active slide
indexh, indexh,
indexv, indexv,
@ -145,9 +142,6 @@ var Reveal = (function(){
// Throttles mouse wheel navigation // Throttles mouse wheel navigation
lastMouseWheelStep = 0, lastMouseWheelStep = 0,
// An interval used to automatically move on to the next slide
autoSlideTimeout = 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,
@ -160,8 +154,14 @@ var Reveal = (function(){
// Flags if the interaction event listeners are bound // Flags if the interaction event listeners are bound
eventsAreBound = false, eventsAreBound = false,
// A visual component used to control auto slide playback // The current auto-slide duration
autoSlide = 0,
// Auto slide properties
autoSlidePlayer, autoSlidePlayer,
autoSlideTimeout = 0,
autoSlideStartTime = -1,
autoSlidePaused = false,
// Holds information about the currently ongoing touch input // Holds information about the currently ongoing touch input
touch = { touch = {
@ -574,12 +574,15 @@ var Reveal = (function(){
enablePreviewLinks( '[data-preview-link]' ); enablePreviewLinks( '[data-preview-link]' );
} }
if( config.autoSlide && config.autoSlideStoppable ) { // Auto-slide playback controls
if( config.autoSlide && config.autoSlideStoppable && features.canvas && features.requestAnimationFrame ) {
autoSlidePlayer = new Playback( dom.wrapper, function() { autoSlidePlayer = new Playback( dom.wrapper, function() {
return 0.5; return Math.min( Math.max( ( Date.now() - autoSlideStartTime ) / autoSlide, 0 ), 1 );
} ); } );
autoSlidePlayer.setPlaying( true ); autoSlidePlayer.on( 'click', function() {
autoSlidePaused ? resumeAutoSlide() : pauseAutoSlide();
} );
} }
else if( autoSlidePlayer ) { else if( autoSlidePlayer ) {
autoSlidePlayer.destroy(); autoSlidePlayer.destroy();
@ -1607,6 +1610,18 @@ var Reveal = (function(){
// Update the URL hash // Update the URL hash
writeURL(); writeURL();
// If the current slide has a data-autoslide use that,
// otherwise use the config.autoSlide value
var slideAutoSlide = currentSlide.getAttribute( 'data-autoslide' );
if( slideAutoSlide ) {
autoSlide = parseInt( slideAutoSlide, 10 );
}
else {
autoSlide = config.autoSlide;
}
cueAutoSlide();
} }
/** /**
@ -1717,18 +1732,6 @@ var Reveal = (function(){
state = state.concat( slideState.split( ' ' ) ); state = state.concat( slideState.split( ' ' ) );
} }
// If this slide has a data-autoslide attribute associated use this as
// autoSlide value otherwise use the global configured time
var slideAutoSlide = slides[index].getAttribute( 'data-autoslide' );
if( slideAutoSlide ) {
autoSlide = parseInt( slideAutoSlide, 10 );
}
else {
autoSlide = config.autoSlide;
}
cueAutoSlide();
} }
else { else {
// Since there are no slides we can't be anywhere beyond the // Since there are no slides we can't be anywhere beyond the
@ -2256,12 +2259,24 @@ var Reveal = (function(){
function cueAutoSlide() { function cueAutoSlide() {
clearTimeout( autoSlideTimeout ); clearTimeout( autoSlideTimeout );
autoSlideTimeout = -1;
// Cue the next auto-slide if enabled autoSlideStartTime = Date.now();
if( autoSlide && !isPaused() && !isOverview() ) {
// Cue the next auto-slide if:
// - There is an autoSlide value
// - Auto-sliding isn't paused by the user
// - The presentation isn't paused
// - The overview isn't active
// - The presentation isn't over
if( autoSlide && !autoSlidePaused && !isPaused() && !isOverview() && ( !Reveal.isLastSlide() || config.loop === true ) ) {
autoSlideTimeout = setTimeout( navigateNext, autoSlide ); autoSlideTimeout = setTimeout( navigateNext, autoSlide );
} }
if( autoSlidePlayer ) {
autoSlidePlayer.setPlaying( autoSlideTimeout !== -1 );
}
} }
/** /**
@ -2273,6 +2288,24 @@ var Reveal = (function(){
} }
function pauseAutoSlide() {
autoSlidePaused = true;
clearTimeout( autoSlideTimeout );
if( autoSlidePlayer ) {
autoSlidePlayer.setPlaying( false );
}
}
function resumeAutoSlide() {
autoSlidePaused = false;
cueAutoSlide();
}
function navigateLeft() { function navigateLeft() {
// Reverse for RTL // Reverse for RTL
@ -2376,8 +2409,7 @@ var Reveal = (function(){
function onUserInput( event ) { function onUserInput( event ) {
if( config.autoSlideStoppable ) { if( config.autoSlideStoppable ) {
config.autoSlide = 0; pauseAutoSlide();
cancelAutoSlide();
} }
} }
@ -2387,6 +2419,8 @@ var Reveal = (function(){
*/ */
function onDocumentKeyDown( event ) { function onDocumentKeyDown( event ) {
onUserInput( event );
// Check if there's a focused element that could be using // Check if there's a focused element that could be using
// the keyboard // the keyboard
var activeElement = document.activeElement; var activeElement = document.activeElement;
@ -2488,8 +2522,6 @@ var Reveal = (function(){
// another timeout // another timeout
cueAutoSlide(); cueAutoSlide();
onUserInput( event );
} }
/** /**
@ -2498,6 +2530,8 @@ var Reveal = (function(){
*/ */
function onTouchStart( event ) { function onTouchStart( event ) {
onUserInput( event );
touch.startX = event.touches[0].clientX; touch.startX = event.touches[0].clientX;
touch.startY = event.touches[0].clientY; touch.startY = event.touches[0].clientY;
touch.startCount = event.touches.length; touch.startCount = event.touches.length;
@ -2514,8 +2548,6 @@ var Reveal = (function(){
} ); } );
} }
onUserInput( event );
} }
/** /**
@ -2617,13 +2649,13 @@ var Reveal = (function(){
*/ */
function onPointerDown( event ) { function onPointerDown( event ) {
onUserInput( event );
if( event.pointerType === event.MSPOINTER_TYPE_TOUCH ) { if( event.pointerType === event.MSPOINTER_TYPE_TOUCH ) {
event.touches = [{ clientX: event.clientX, clientY: event.clientY }]; event.touches = [{ clientX: event.clientX, clientY: event.clientY }];
onTouchStart( event ); onTouchStart( event );
} }
onUserInput( event );
} }
/** /**
@ -2680,6 +2712,8 @@ var Reveal = (function(){
*/ */
function onProgressClicked( event ) { function onProgressClicked( event ) {
onUserInput( event );
event.preventDefault(); event.preventDefault();
var slidesTotal = toArray( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).length; var slidesTotal = toArray( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).length;
@ -2687,19 +2721,17 @@ var Reveal = (function(){
slide( slideIndex ); slide( slideIndex );
onUserInput( event );
} }
/** /**
* Event handler for navigation control buttons. * Event handler for navigation control buttons.
*/ */
function onNavigateLeftClicked( event ) { event.preventDefault(); navigateLeft(); onUserInput(); } function onNavigateLeftClicked( event ) { event.preventDefault(); onUserInput(); navigateLeft(); }
function onNavigateRightClicked( event ) { event.preventDefault(); navigateRight(); onUserInput(); } function onNavigateRightClicked( event ) { event.preventDefault(); onUserInput(); navigateRight(); }
function onNavigateUpClicked( event ) { event.preventDefault(); navigateUp(); onUserInput(); } function onNavigateUpClicked( event ) { event.preventDefault(); onUserInput(); navigateUp(); }
function onNavigateDownClicked( event ) { event.preventDefault(); navigateDown(); onUserInput(); } function onNavigateDownClicked( event ) { event.preventDefault(); onUserInput(); navigateDown(); }
function onNavigatePrevClicked( event ) { event.preventDefault(); navigatePrev(); onUserInput(); } function onNavigatePrevClicked( event ) { event.preventDefault(); onUserInput(); navigatePrev(); }
function onNavigateNextClicked( event ) { event.preventDefault(); navigateNext(); onUserInput(); } function onNavigateNextClicked( event ) { event.preventDefault(); onUserInput(); navigateNext(); }
/** /**
* Handler for the window level 'hashchange' event. * Handler for the window level 'hashchange' event.
@ -2845,12 +2877,14 @@ var Reveal = (function(){
Playback.prototype.render = function() { Playback.prototype.render = function() {
var progress = this.playing ? this.progress : 0;
var radius = ( this.size / 2 ) - this.thickness, var radius = ( this.size / 2 ) - this.thickness,
x = this.size / 2, x = this.size / 2,
y = this.size / 2; y = this.size / 2;
var startAngle = - Math.PI / 2; var startAngle = - Math.PI / 2;
var endAngle = startAngle + ( this.progress * ( Math.PI * 2 ) ); var endAngle = startAngle + ( progress * ( Math.PI * 2 ) );
this.context.save(); this.context.save();
this.context.clearRect( 0, 0, this.size, this.size ); this.context.clearRect( 0, 0, this.size, this.size );
@ -2875,6 +2909,26 @@ var Reveal = (function(){
this.context.strokeStyle = '#fff'; this.context.strokeStyle = '#fff';
this.context.stroke(); this.context.stroke();
var iconSize = 14;
this.context.translate( x - ( iconSize / 2 ), y - ( iconSize / 2 ) );
// Draw play/pause icons
if( this.playing ) {
this.context.fillStyle = '#fff';
this.context.fillRect( 0, 0, iconSize / 2 - 2, iconSize );
this.context.fillRect( iconSize / 2 + 2, 0, iconSize / 2 - 2, iconSize );
}
else {
this.context.beginPath();
this.context.translate( 2, 0 );
this.context.moveTo( 0, 0 );
this.context.lineTo( iconSize - 2, iconSize / 2 );
this.context.lineTo( 0, iconSize );
this.context.fillStyle = '#fff';
this.context.fill();
}
this.context.restore(); this.context.restore();
}; };
@ -2887,6 +2941,14 @@ var Reveal = (function(){
}; };
Playback.prototype.on = function( type, listener ) {
this.canvas.addEventListener( type, listener, false );
};
Playback.prototype.off = function( type, listener ) {
this.canvas.removeEventListener( type, listener, false );
};
// --------------------------------------------------------------------// // --------------------------------------------------------------------//
// ------------------------------- API --------------------------------// // ------------------------------- API --------------------------------//

4
js/reveal.min.js vendored

File diff suppressed because one or more lines are too long