From 11293d7c9415862007dbc1e3936b0fcbf4626da1 Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Mon, 26 Jan 2015 20:38:21 +0100 Subject: [PATCH 1/7] refactoring and optimization of overview mode --- css/reveal.css | 17 +++++---- css/reveal.scss | 14 ++++--- js/reveal.js | 99 +++++++++++++++++++++++++++++++++---------------- 3 files changed, 87 insertions(+), 43 deletions(-) diff --git a/css/reveal.css b/css/reveal.css index 35a048fa..b1984868 100644 --- a/css/reveal.css +++ b/css/reveal.css @@ -639,9 +639,10 @@ body { opacity: 1 !important; visibility: visible !important; cursor: pointer; - background: rgba(0, 0, 0, 0.1); -moz-box-sizing: border-box; - box-sizing: border-box; } + box-sizing: border-box; + outline: 10px solid rgba(150, 150, 150, 0.1); + outline-offset: 10px; } .reveal.overview .slides section, .reveal.overview-deactivating .slides section { -webkit-transition: none !important; @@ -657,16 +658,14 @@ body { opacity: 1; cursor: pointer; } -.reveal.overview .slides section:hover { - background: rgba(0, 0, 0, 0.3); } - -.reveal.overview .slides section.present { - background: rgba(0, 0, 0, 0.3); } +.reveal.overview .slides section:hover, .reveal.overview .slides section.present { + outline: 10px solid rgba(150, 150, 150, 0.5); } .reveal.overview .slides > section.stack { padding: 0; top: 0 !important; background: none; + outline: none; overflow: visible; } .reveal.overview .backgrounds { @@ -681,6 +680,10 @@ body { -webkit-transition: none !important; transition: none !important; } +.reveal.overview-animated .slides { + -webkit-transition: -webkit-transform 0.4s ease; + transition: transform 0.4s ease; } + /********************************************* * PAUSED MODE *********************************************/ diff --git a/css/reveal.scss b/css/reveal.scss index a1c14a1e..02587fbd 100644 --- a/css/reveal.scss +++ b/css/reveal.scss @@ -753,8 +753,9 @@ body { opacity: 1 !important; visibility: visible !important; cursor: pointer; - background: rgba(0,0,0,0.1); box-sizing: border-box; + outline: 10px solid rgba(150,150,150,0.1); + outline-offset: 10px; } .reveal.overview .slides section, .reveal.overview-deactivating .slides section { @@ -771,16 +772,15 @@ body { opacity: 1; cursor: pointer; } - .reveal.overview .slides section:hover { - background: rgba(0,0,0,0.3); - } + .reveal.overview .slides section:hover, .reveal.overview .slides section.present { - background: rgba(0,0,0,0.3); + outline: 10px solid rgba(150,150,150,0.5); } .reveal.overview .slides>section.stack { padding: 0; top: 0 !important; background: none; + outline: none; overflow: visible; } @@ -796,6 +796,10 @@ body { transition: none !important; } +.reveal.overview-animated .slides { + transition: transform 0.4s ease; +} + /********************************************* * PAUSED MODE diff --git a/js/reveal.js b/js/reveal.js index 9634c6bc..74fcf5f0 100644 --- a/js/reveal.js +++ b/js/reveal.js @@ -147,6 +147,9 @@ // Flags if reveal.js is loaded (has dispatched the 'ready' event) loaded = false, + // Flags if the overview mode is currently active + overview = false, + // The horizontal and vertical index of the currently active slide indexh, indexv, @@ -165,8 +168,9 @@ // The current scale of the presentation (see width/height config) scale = 1, - // The current z position of the presentation container - z = 0, + // The transform that is currently applied to the slides container + slidesTransform = '', + layoutTransform = '', // Cached references to DOM elements dom = {}, @@ -1058,6 +1062,12 @@ } + function transformSlides() { + + transformElement( dom.slides, layoutTransform ? layoutTransform + ' ' + slidesTransform : slidesTransform ); + + } + /** * Injects the given CSS styles into the DOM. */ @@ -1446,7 +1456,6 @@ var size = getComputedSlideSize(); var slidePadding = 20; // TODO Dig this out of DOM - var zTransform = z !== 0 ? 'translateZ(-'+ z +'px)' : ''; // Layout the contents of the slides layoutSlideContents( config.width, config.height, slidePadding ); @@ -1468,13 +1477,12 @@ dom.slides.style.top = ''; dom.slides.style.bottom = ''; dom.slides.style.right = ''; - transformElement( dom.slides, zTransform ); + layoutTransform = ''; } else { // Prefer zooming in desktop Chrome so that content remains crisp if( !isMobileDevice && /chrome/i.test( navigator.userAgent ) && typeof dom.slides.style.zoom !== 'undefined' ) { dom.slides.style.zoom = scale; - transformElement( dom.slides, zTransform ); } // Apply scale transform as a fallback else { @@ -1482,10 +1490,12 @@ dom.slides.style.top = '50%'; dom.slides.style.bottom = 'auto'; dom.slides.style.right = 'auto'; - transformElement( dom.slides, 'translate(-50%, -50%) scale('+ scale +') ' + zTransform ); + layoutTransform = 'translate(-50%, -50%) scale('+ scale +')'; } } + transformSlides(); + // Select all slides, vertical and horizontal var slides = toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ); @@ -1633,20 +1643,23 @@ function activateOverview() { // Only proceed if enabled in config - if( config.overview ) { + if( config.overview && !isOverview() ) { + + overview = true; + + dom.wrapper.classList.add( 'overview' ); + dom.wrapper.classList.remove( 'overview-deactivating' ); + + setTimeout( function() { + dom.wrapper.classList.add( 'overview-animated' ); + }, 1 ); // Don't auto-slide while in overview mode cancelAutoSlide(); - var wasActive = dom.wrapper.classList.contains( 'overview' ); - - // Set the depth of the presentation. This determinse how far we - // zoom out and varies based on display size. It gets applied at - // the layout step. - z = window.innerWidth < 400 ? 1000 : 2500; - - dom.wrapper.classList.add( 'overview' ); - dom.wrapper.classList.remove( 'overview-deactivating' ); + var margin = 70; + var slideWidth = config.width + margin, + slideHeight = config.height + margin; // Move the backgrounds element into the slide container to // that the same scaling is applied @@ -1658,9 +1671,9 @@ for( var i = 0, len1 = horizontalSlides.length; i < len1; i++ ) { var hslide = horizontalSlides[i], hbackground = horizontalBackgrounds[i], - hoffset = config.rtl ? -105 : 105; + hoffset = config.rtl ? -slideWidth : slideWidth; - var htransform = 'translate(' + ( ( i - indexh ) * hoffset ) + '%, 0%)'; + var htransform = 'translateX(' + ( i * hoffset ) + 'px)'; hslide.setAttribute( 'data-index-h', i ); @@ -1679,7 +1692,7 @@ var vslide = verticalSlides[j], vbackground = verticalBackgrounds[j]; - var vtransform = 'translate(0%, ' + ( ( j - verticalIndex ) * 105 ) + '%)'; + var vtransform = 'translateY(' + ( j * slideHeight ) + 'px)'; vslide.setAttribute( 'data-index-h', i ); vslide.setAttribute( 'data-index-v', j ); @@ -1702,22 +1715,38 @@ } updateSlidesVisibility(); + updateOverview(); layout(); - if( !wasActive ) { - // Notify observers of the overview showing - dispatchEvent( 'overviewshown', { - 'indexh': indexh, - 'indexv': indexv, - 'currentSlide': currentSlide - } ); - } + // Notify observers of the overview showing + dispatchEvent( 'overviewshown', { + 'indexh': indexh, + 'indexv': indexv, + 'currentSlide': currentSlide + } ); } } + function updateOverview() { + + var z = window.innerWidth < 400 ? 1000 : 2500; + var margin = 70; + var slideWidth = config.width + margin, + slideHeight = config.height + margin; + + slidesTransform = [ + 'translateX('+ ( -indexh * slideWidth ) +'px)', + 'translateY('+ ( -indexv * slideHeight ) +'px)', + 'translateZ('+ ( -z ) +'px)' + ].join( ' ' ); + + transformSlides(); + + } + /** * Exits the slide overview and enters the currently * active slide. @@ -1727,11 +1756,17 @@ // Only proceed if enabled in config if( config.overview ) { + slidesTransform = ''; + + overview = false; + dom.wrapper.classList.remove( 'overview' ); // Move the background element back out dom.wrapper.appendChild( dom.background ); + dom.wrapper.classList.remove( 'overview-animated' ); + // Temporarily add a class so that transitions can do different things // depending on whether they are exiting/entering overview, or just // moving from slide to slide @@ -1755,6 +1790,8 @@ slide( indexh, indexv ); + layout(); + cueAutoSlide(); // Notify observers of the overview hiding @@ -1793,7 +1830,7 @@ */ function isOverview() { - return dom.wrapper.classList.contains( 'overview' ); + return overview; } @@ -1995,7 +2032,7 @@ // If the overview is active, re-activate it to update positions if( isOverview() ) { - activateOverview(); + updateOverview(); } // Find the current horizontal slide and any possible vertical slides @@ -2289,11 +2326,11 @@ // The number of steps away from the present slide that will // be visible - var viewDistance = isOverview() ? 10 : config.viewDistance; + var viewDistance = isOverview() ? 7 : config.viewDistance; // Limit view distance on weaker devices if( isMobileDevice ) { - viewDistance = isOverview() ? 6 : 2; + viewDistance = isOverview() ? 7 : 2; } // Limit view distance on weaker devices From e29c706533c227682cfde1ac0b187e90738b9bbc Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Tue, 27 Jan 2015 09:21:49 +0100 Subject: [PATCH 2/7] further overview refactoring --- css/reveal.css | 10 ++-- css/reveal.scss | 7 +-- js/reveal.js | 123 +++++++++++++++++++++++++++--------------------- 3 files changed, 78 insertions(+), 62 deletions(-) diff --git a/css/reveal.css b/css/reveal.css index b1984868..69b7cf9e 100644 --- a/css/reveal.css +++ b/css/reveal.css @@ -645,8 +645,8 @@ body { outline-offset: 10px; } .reveal.overview .slides section, .reveal.overview-deactivating .slides section { - -webkit-transition: none !important; - transition: none !important; } + -webkit-transition: none; + transition: none; } .reveal.overview .slides section .fragment { opacity: 1; } @@ -677,10 +677,10 @@ body { visibility: visible; } .reveal.overview .backgrounds .slide-background, .reveal.overview-deactivating .backgrounds .slide-background { - -webkit-transition: none !important; - transition: none !important; } + -webkit-transition: none; + transition: none; } -.reveal.overview-animated .slides { +.reveal.overview-animated .slides, .reveal.overview-animated .slides section { -webkit-transition: -webkit-transform 0.4s ease; transition: transform 0.4s ease; } diff --git a/css/reveal.scss b/css/reveal.scss index 02587fbd..b3f3bdc5 100644 --- a/css/reveal.scss +++ b/css/reveal.scss @@ -759,7 +759,7 @@ body { } .reveal.overview .slides section, .reveal.overview-deactivating .slides section { - transition: none !important; + transition: none; } .reveal.overview .slides section .fragment { opacity: 1; @@ -793,10 +793,11 @@ body { } .reveal.overview .backgrounds .slide-background, .reveal.overview-deactivating .backgrounds .slide-background { - transition: none !important; + transition: none; } -.reveal.overview-animated .slides { +.reveal.overview-animated .slides, +.reveal.overview-animated .slides section { transition: transform 0.4s ease; } diff --git a/js/reveal.js b/js/reveal.js index 74fcf5f0..ddbe8009 100644 --- a/js/reveal.js +++ b/js/reveal.js @@ -1636,9 +1636,6 @@ /** * Displays the overview of slides (quick nav) by * scaling down and arranging all slide elements. - * - * Experimental feature, might be dropped if perf - * can't be improved. */ function activateOverview() { @@ -1657,64 +1654,32 @@ // Don't auto-slide while in overview mode cancelAutoSlide(); - var margin = 70; - var slideWidth = config.width + margin, - slideHeight = config.height + margin; - // Move the backgrounds element into the slide container to // that the same scaling is applied dom.slides.appendChild( dom.background ); - var horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ), - horizontalBackgrounds = dom.background.childNodes; + // Bind events so that clicking on a slide navigates to it + toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( hslide, h ) { - for( var i = 0, len1 = horizontalSlides.length; i < len1; i++ ) { - var hslide = horizontalSlides[i], - hbackground = horizontalBackgrounds[i], - hoffset = config.rtl ? -slideWidth : slideWidth; - - var htransform = 'translateX(' + ( i * hoffset ) + 'px)'; - - hslide.setAttribute( 'data-index-h', i ); - - // Apply CSS transform - transformElement( hslide, htransform ); - transformElement( hbackground, htransform ); + hslide.setAttribute( 'data-index-h', h ); if( hslide.classList.contains( 'stack' ) ) { + toArray( hslide.querySelectorAll( 'section' ) ).forEach( function( vslide, v ) { - var verticalSlides = hslide.querySelectorAll( 'section' ), - verticalBackgrounds = hbackground.querySelectorAll( '.slide-background' ); - - for( var j = 0, len2 = verticalSlides.length; j < len2; j++ ) { - var verticalIndex = i === indexh ? indexv : getPreviousVerticalIndex( hslide ); - - var vslide = verticalSlides[j], - vbackground = verticalBackgrounds[j]; - - var vtransform = 'translateY(' + ( j * slideHeight ) + 'px)'; - - vslide.setAttribute( 'data-index-h', i ); - vslide.setAttribute( 'data-index-v', j ); - - // Apply CSS transform - transformElement( vslide, vtransform ); - transformElement( vbackground, vtransform ); - - // Navigate to this slide on click + vslide.setAttribute( 'data-index-h', h ); + vslide.setAttribute( 'data-index-v', v ); vslide.addEventListener( 'click', onOverviewSlideClicked, true ); - } + } ); } else { - - // Navigate to this slide on click hslide.addEventListener( 'click', onOverviewSlideClicked, true ); - } - } + + } ); updateSlidesVisibility(); + layoutOverview(); updateOverview(); layout(); @@ -1730,17 +1695,64 @@ } - function updateOverview() { + /** + * Moves the slides into a grid for display in the + * overview mode. + */ + function layoutOverview() { - var z = window.innerWidth < 400 ? 1000 : 2500; var margin = 70; var slideWidth = config.width + margin, slideHeight = config.height + margin; + // Reverse in RTL mode + if( config.rtl ) { + slideWidth = -slideWidth; + } + + // Layout slides + toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( hslide, h ) { + transformElement( hslide, 'translateX(' + ( h * slideWidth ) + 'px)' ); + + if( hslide.classList.contains( 'stack' ) ) { + + toArray( hslide.querySelectorAll( 'section' ) ).forEach( function( vslide, v ) { + transformElement( vslide, 'translateY(' + ( v * slideHeight ) + 'px)' ); + } ); + + } + } ); + + // Layout slide backgrounds + toArray( dom.background.childNodes ).forEach( function( hbackground, h ) { + transformElement( hbackground, 'translateX(' + ( h * slideWidth ) + 'px)' ); + + toArray( hbackground.querySelectorAll( '.slide-background' ) ).forEach( function( vbackground, v ) { + transformElement( vbackground, 'translateY(' + ( v * slideHeight ) + 'px)' ); + } ); + } ); + + } + + /** + * Moves the overview viewport to the current slides. + * Called each time the current slide changes. + */ + function updateOverview() { + + var margin = 70; + var slideWidth = config.width + margin, + slideHeight = config.height + margin; + + // Reverse in RTL mode + if( config.rtl ) { + slideWidth = -slideWidth; + } + slidesTransform = [ 'translateX('+ ( -indexh * slideWidth ) +'px)', 'translateY('+ ( -indexv * slideHeight ) +'px)', - 'translateZ('+ ( -z ) +'px)' + 'translateZ('+ ( window.innerWidth < 400 ? -1000 : -2500 ) +'px)' ].join( ' ' ); transformSlides(); @@ -1761,10 +1773,6 @@ overview = false; dom.wrapper.classList.remove( 'overview' ); - - // Move the background element back out - dom.wrapper.appendChild( dom.background ); - dom.wrapper.classList.remove( 'overview-animated' ); // Temporarily add a class so that transitions can do different things @@ -1776,6 +1784,9 @@ dom.wrapper.classList.remove( 'overview-deactivating' ); }, 1 ); + // Move the background element back out + dom.wrapper.appendChild( dom.background ); + // Clean up changes made to slides toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) { transformElement( slide, '' ); @@ -2145,6 +2156,10 @@ formatEmbeddedContent(); + if( isOverview() ) { + layoutOverview(); + } + } /** @@ -2326,11 +2341,11 @@ // The number of steps away from the present slide that will // be visible - var viewDistance = isOverview() ? 7 : config.viewDistance; + var viewDistance = isOverview() ? 10 : config.viewDistance; // Limit view distance on weaker devices if( isMobileDevice ) { - viewDistance = isOverview() ? 7 : 2; + viewDistance = isOverview() ? 6 : 2; } // Limit view distance on weaker devices From c8569e2d9ff675b806e5d5bf94ba1a07d121e74b Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Tue, 27 Jan 2015 19:27:55 +0100 Subject: [PATCH 3/7] cross browser adjustments for overview mode --- css/reveal.css | 112 +++++++++++++++++++--------------------- css/reveal.scss | 133 +++++++++++++++++++++++++----------------------- js/reveal.js | 22 +++++--- 3 files changed, 136 insertions(+), 131 deletions(-) diff --git a/css/reveal.css b/css/reveal.css index 69b7cf9e..2e18ade5 100644 --- a/css/reveal.css +++ b/css/reveal.css @@ -624,66 +624,6 @@ body { -webkit-transition: none; transition: none; } -/********************************************* - * OVERVIEW - *********************************************/ -.reveal.overview { - -webkit-perspective-origin: 50% 50%; - perspective-origin: 50% 50%; - -webkit-perspective: 700px; - perspective: 700px; } - -.reveal.overview .slides section { - height: 700px; - overflow: hidden; - opacity: 1 !important; - visibility: visible !important; - cursor: pointer; - -moz-box-sizing: border-box; - box-sizing: border-box; - outline: 10px solid rgba(150, 150, 150, 0.1); - outline-offset: 10px; } - -.reveal.overview .slides section, .reveal.overview-deactivating .slides section { - -webkit-transition: none; - transition: none; } - -.reveal.overview .slides section .fragment { - opacity: 1; } - -.reveal.overview .slides section:after, .reveal.overview .slides section:before { - display: none !important; } - -.reveal.overview .slides section > section { - opacity: 1; - cursor: pointer; } - -.reveal.overview .slides section:hover, .reveal.overview .slides section.present { - outline: 10px solid rgba(150, 150, 150, 0.5); } - -.reveal.overview .slides > section.stack { - padding: 0; - top: 0 !important; - background: none; - outline: none; - overflow: visible; } - -.reveal.overview .backgrounds { - -webkit-perspective: inherit; - perspective: inherit; } - -.reveal.overview .backgrounds .slide-background { - opacity: 1; - visibility: visible; } - -.reveal.overview .backgrounds .slide-background, .reveal.overview-deactivating .backgrounds .slide-background { - -webkit-transition: none; - transition: none; } - -.reveal.overview-animated .slides, .reveal.overview-animated .slides section { - -webkit-transition: -webkit-transform 0.4s ease; - transition: transform 0.4s ease; } - /********************************************* * PAUSED MODE *********************************************/ @@ -904,6 +844,58 @@ body { -webkit-transition-duration: 1200ms; transition-duration: 1200ms; } +/********************************************* + * OVERVIEW + *********************************************/ +.reveal.overview { + -webkit-perspective-origin: 50% 50%; + perspective-origin: 50% 50%; + -webkit-perspective: 700px; + perspective: 700px; } + .reveal.overview .slides section { + height: 700px; + opacity: 1 !important; + overflow: hidden; + visibility: visible !important; + cursor: pointer; + -moz-box-sizing: border-box; + box-sizing: border-box; } + .reveal.overview .slides section:hover, .reveal.overview .slides section.present { + outline: 10px solid rgba(150, 150, 150, 0.4); + outline-offset: 10px; } + .reveal.overview .slides section .fragment { + opacity: 1; + -webkit-transition: none; + transition: none; } + .reveal.overview .slides section:after, .reveal.overview .slides section:before { + display: none !important; } + .reveal.overview .slides > section.stack { + padding: 0; + top: 0 !important; + background: none; + outline: none; + overflow: visible; } + .reveal.overview .backgrounds { + -webkit-perspective: inherit; + perspective: inherit; } + .reveal.overview .backgrounds .slide-background { + opacity: 1; + visibility: visible; + outline: 10px solid rgba(150, 150, 150, 0.1); + outline-offset: 10px; } + +.reveal.overview .slides section, .reveal.overview-deactivating .slides section { + -webkit-transition: none; + transition: none; } + +.reveal.overview .backgrounds .slide-background, .reveal.overview-deactivating .backgrounds .slide-background { + -webkit-transition: none; + transition: none; } + +.reveal.overview-animated .slides, .reveal.overview-animated .slides section, .reveal.overview-animated .backgrounds .slide-background { + -webkit-transition: -webkit-transform 0.4s ease; + transition: transform 0.4s ease; } + /********************************************* * RTL SUPPORT *********************************************/ diff --git a/css/reveal.scss b/css/reveal.scss index b3f3bdc5..70fe2c1a 100644 --- a/css/reveal.scss +++ b/css/reveal.scss @@ -739,69 +739,6 @@ body { } -/********************************************* - * OVERVIEW - *********************************************/ - -.reveal.overview { - perspective-origin: 50% 50%; - perspective: 700px; -} -.reveal.overview .slides section { - height: 700px; - overflow: hidden; - opacity: 1 !important; - visibility: visible !important; - cursor: pointer; - box-sizing: border-box; - outline: 10px solid rgba(150,150,150,0.1); - outline-offset: 10px; -} -.reveal.overview .slides section, -.reveal.overview-deactivating .slides section { - transition: none; -} -.reveal.overview .slides section .fragment { - opacity: 1; -} -.reveal.overview .slides section:after, -.reveal.overview .slides section:before { - display: none !important; -} -.reveal.overview .slides section>section { - opacity: 1; - cursor: pointer; -} - .reveal.overview .slides section:hover, - .reveal.overview .slides section.present { - outline: 10px solid rgba(150,150,150,0.5); - } -.reveal.overview .slides>section.stack { - padding: 0; - top: 0 !important; - background: none; - outline: none; - overflow: visible; -} - -.reveal.overview .backgrounds { - perspective: inherit; -} -.reveal.overview .backgrounds .slide-background { - opacity: 1; - visibility: visible; -} -.reveal.overview .backgrounds .slide-background, -.reveal.overview-deactivating .backgrounds .slide-background { - transition: none; -} - -.reveal.overview-animated .slides, -.reveal.overview-animated .slides section { - transition: transform 0.4s ease; -} - - /********************************************* * PAUSED MODE *********************************************/ @@ -1042,6 +979,76 @@ body { } +/********************************************* + * OVERVIEW + *********************************************/ + +.reveal.overview { + perspective-origin: 50% 50%; + perspective: 700px; + + .slides section { + height: 700px; + opacity: 1 !important; + overflow: hidden; + visibility: visible !important; + cursor: pointer; + box-sizing: border-box; + } + .slides section:hover, + .slides section.present { + outline: 10px solid rgba(150,150,150,0.4); + outline-offset: 10px; + } + .slides section .fragment { + opacity: 1; + transition: none; + } + .slides section:after, + .slides section:before { + display: none !important; + } + .slides>section.stack { + padding: 0; + top: 0 !important; + background: none; + outline: none; + overflow: visible; + } + + .backgrounds { + perspective: inherit; + } + + .backgrounds .slide-background { + opacity: 1; + visibility: visible; + + // This can't be applied to the slide itself in Safari + outline: 10px solid rgba(150,150,150,0.1); + outline-offset: 10px; + } +} + +// Disable transitions transitions while we're activating +// or deactivating the overview mode. +.reveal.overview .slides section, +.reveal.overview-deactivating .slides section { + transition: none; +} + +.reveal.overview .backgrounds .slide-background, +.reveal.overview-deactivating .backgrounds .slide-background { + transition: none; +} + +.reveal.overview-animated .slides, +.reveal.overview-animated .slides section, +.reveal.overview-animated .backgrounds .slide-background { + transition: transform 0.4s ease; +} + + /********************************************* * RTL SUPPORT *********************************************/ diff --git a/js/reveal.js b/js/reveal.js index ddbe8009..37c68311 100644 --- a/js/reveal.js +++ b/js/reveal.js @@ -300,7 +300,11 @@ features.touch = !!( 'ontouchstart' in window ); - isMobileDevice = navigator.userAgent.match( /(iphone|ipod|ipad|android)/gi ); + // Transitions in the overview are disabled in desktop and + // mobile Safari since they lag terribly + features.overviewTransitions = !/Version\/[\d\.]+.*Safari/.test( navigator.userAgent ); + + isMobileDevice = /(iphone|ipod|ipad|android)/gi.test( navigator.userAgent ); } @@ -1647,9 +1651,11 @@ dom.wrapper.classList.add( 'overview' ); dom.wrapper.classList.remove( 'overview-deactivating' ); - setTimeout( function() { - dom.wrapper.classList.add( 'overview-animated' ); - }, 1 ); + if( features.overviewTransitions ) { + setTimeout( function() { + dom.wrapper.classList.add( 'overview-animated' ); + }, 1 ); + } // Don't auto-slide while in overview mode cancelAutoSlide(); @@ -1712,12 +1718,12 @@ // Layout slides toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( hslide, h ) { - transformElement( hslide, 'translateX(' + ( h * slideWidth ) + 'px)' ); + transformElement( hslide, 'translate3d(' + ( h * slideWidth ) + 'px, 0, 0)' ); if( hslide.classList.contains( 'stack' ) ) { toArray( hslide.querySelectorAll( 'section' ) ).forEach( function( vslide, v ) { - transformElement( vslide, 'translateY(' + ( v * slideHeight ) + 'px)' ); + transformElement( vslide, 'translate3d(0, ' + ( v * slideHeight ) + 'px, 0)' ); } ); } @@ -1725,10 +1731,10 @@ // Layout slide backgrounds toArray( dom.background.childNodes ).forEach( function( hbackground, h ) { - transformElement( hbackground, 'translateX(' + ( h * slideWidth ) + 'px)' ); + transformElement( hbackground, 'translate3d(' + ( h * slideWidth ) + 'px, 0, 0)' ); toArray( hbackground.querySelectorAll( '.slide-background' ) ).forEach( function( vbackground, v ) { - transformElement( vbackground, 'translateY(' + ( v * slideHeight ) + 'px)' ); + transformElement( vbackground, 'translate3d(0, ' + ( v * slideHeight ) + 'px, 0)' ); } ); } ); From 64e72781b4d576a2a32e7c4b3e1692d03a182c7d Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Wed, 28 Jan 2015 08:33:50 +0100 Subject: [PATCH 4/7] ensure overview indices are up to date if a slide moves --- js/reveal.js | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/js/reveal.js b/js/reveal.js index 37c68311..9ed7b7e3 100644 --- a/js/reveal.js +++ b/js/reveal.js @@ -1664,24 +1664,11 @@ // that the same scaling is applied dom.slides.appendChild( dom.background ); - // Bind events so that clicking on a slide navigates to it - toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( hslide, h ) { - - hslide.setAttribute( 'data-index-h', h ); - - if( hslide.classList.contains( 'stack' ) ) { - toArray( hslide.querySelectorAll( 'section' ) ).forEach( function( vslide, v ) { - - vslide.setAttribute( 'data-index-h', h ); - vslide.setAttribute( 'data-index-v', v ); - vslide.addEventListener( 'click', onOverviewSlideClicked, true ); - - } ); + // Clicking on an overview slide navigates to it + toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) { + if( !slide.classList.contains( 'stack' ) ) { + slide.addEventListener( 'click', onOverviewSlideClicked, true ); } - else { - hslide.addEventListener( 'click', onOverviewSlideClicked, true ); - } - } ); updateSlidesVisibility(); @@ -1718,11 +1705,15 @@ // Layout slides toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( hslide, h ) { + hslide.setAttribute( 'data-index-h', h ); transformElement( hslide, 'translate3d(' + ( h * slideWidth ) + 'px, 0, 0)' ); if( hslide.classList.contains( 'stack' ) ) { toArray( hslide.querySelectorAll( 'section' ) ).forEach( function( vslide, v ) { + vslide.setAttribute( 'data-index-h', h ); + vslide.setAttribute( 'data-index-v', v ); + transformElement( vslide, 'translate3d(0, ' + ( v * slideHeight ) + 'px, 0)' ); } ); @@ -1997,7 +1988,7 @@ // If no vertical index is specified and the upcoming slide is a // stack, resume at its previous vertical index - if( v === undefined ) { + if( v === undefined && !isOverview() ) { v = getPreviousVerticalIndex( horizontalSlides[ h ] ); } From 18e29a898af3fb2d412320ab0c784dfc46bf2a06 Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Thu, 29 Jan 2015 11:59:47 +0100 Subject: [PATCH 5/7] cleaner approach to applying transforms to slides container --- js/reveal.js | 51 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/js/reveal.js b/js/reveal.js index 9ed7b7e3..61afab4d 100644 --- a/js/reveal.js +++ b/js/reveal.js @@ -168,9 +168,9 @@ // The current scale of the presentation (see width/height config) scale = 1, - // The transform that is currently applied to the slides container - slidesTransform = '', - layoutTransform = '', + // CSS transform that is currently applied to the slides container, + // split into two groups + slidesTransform = { layout: '', overview: '' }, // Cached references to DOM elements dom = {}, @@ -301,7 +301,7 @@ features.touch = !!( 'ontouchstart' in window ); // Transitions in the overview are disabled in desktop and - // mobile Safari since they lag terribly + // mobile Safari due to lag features.overviewTransitions = !/Version\/[\d\.]+.*Safari/.test( navigator.userAgent ); isMobileDevice = /(iphone|ipod|ipad|android)/gi.test( navigator.userAgent ); @@ -1066,9 +1066,25 @@ } - function transformSlides() { + /** + * Applies CSS transforms to the slides container. The container + * is transformed from two separate sources: layout and the overview + * mode. + */ + function transformSlides( transforms ) { + + // Pick up new transforms from arguments + if( transforms.layout ) slidesTransform.layout = transforms.layout; + if( transforms.overview ) slidesTransform.overview = transforms.overview; + + // Apply the transforms to the slides container + if( slidesTransform.layout ) { + transformElement( dom.slides, slidesTransform.layout + ' ' + slidesTransform.overview ); + } + else { + transformElement( dom.slides, slidesTransform.overview ); + } - transformElement( dom.slides, layoutTransform ? layoutTransform + ' ' + slidesTransform : slidesTransform ); } @@ -1481,12 +1497,13 @@ dom.slides.style.top = ''; dom.slides.style.bottom = ''; dom.slides.style.right = ''; - layoutTransform = ''; + transformSlides( { layout: '' } ); } else { // Prefer zooming in desktop Chrome so that content remains crisp if( !isMobileDevice && /chrome/i.test( navigator.userAgent ) && typeof dom.slides.style.zoom !== 'undefined' ) { dom.slides.style.zoom = scale; + transformSlides( { layout: '' } ); } // Apply scale transform as a fallback else { @@ -1494,12 +1511,10 @@ dom.slides.style.top = '50%'; dom.slides.style.bottom = 'auto'; dom.slides.style.right = 'auto'; - layoutTransform = 'translate(-50%, -50%) scale('+ scale +')'; + transformSlides( { layout: 'translate(-50%, -50%) scale('+ scale +')' } ); } } - transformSlides(); - // Select all slides, vertical and horizontal var slides = toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ); @@ -1746,13 +1761,13 @@ slideWidth = -slideWidth; } - slidesTransform = [ - 'translateX('+ ( -indexh * slideWidth ) +'px)', - 'translateY('+ ( -indexv * slideHeight ) +'px)', - 'translateZ('+ ( window.innerWidth < 400 ? -1000 : -2500 ) +'px)' - ].join( ' ' ); - - transformSlides(); + transformSlides( { + overview: [ + 'translateX('+ ( -indexh * slideWidth ) +'px)', + 'translateY('+ ( -indexv * slideHeight ) +'px)', + 'translateZ('+ ( window.innerWidth < 400 ? -1000 : -2500 ) +'px)' + ].join( ' ' ) + } ); } @@ -1765,7 +1780,7 @@ // Only proceed if enabled in config if( config.overview ) { - slidesTransform = ''; + transformSlides( { overview: '' } ); overview = false; From c8d7451142520c3999335e5ca958d27402071f30 Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Thu, 29 Jan 2015 12:03:02 +0100 Subject: [PATCH 6/7] comments --- js/reveal.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/reveal.js b/js/reveal.js index 61afab4d..ac21f33e 100644 --- a/js/reveal.js +++ b/js/reveal.js @@ -1653,8 +1653,8 @@ } /** - * Displays the overview of slides (quick nav) by - * scaling down and arranging all slide elements. + * Displays the overview of slides (quick nav) by scaling + * down and arranging all slide elements. */ function activateOverview() { @@ -1704,8 +1704,8 @@ } /** - * Moves the slides into a grid for display in the - * overview mode. + * Uses CSS transforms to position all slides in a grid for + * display inside of the overview mode. */ function layoutOverview() { From 8e66876c4e5881d3a85516e0070094bc8b0d8b9f Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Thu, 29 Jan 2015 12:21:05 +0100 Subject: [PATCH 7/7] fix error when exiting overview --- js/reveal.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/js/reveal.js b/js/reveal.js index ac21f33e..ad2d5a37 100644 --- a/js/reveal.js +++ b/js/reveal.js @@ -1074,8 +1074,8 @@ function transformSlides( transforms ) { // Pick up new transforms from arguments - if( transforms.layout ) slidesTransform.layout = transforms.layout; - if( transforms.overview ) slidesTransform.overview = transforms.overview; + if( typeof transforms.layout === 'string' ) slidesTransform.layout = transforms.layout; + if( typeof transforms.overview === 'string' ) slidesTransform.overview = transforms.overview; // Apply the transforms to the slides container if( slidesTransform.layout ) { @@ -1085,7 +1085,6 @@ transformElement( dom.slides, slidesTransform.overview ); } - } /** @@ -1780,8 +1779,6 @@ // Only proceed if enabled in config if( config.overview ) { - transformSlides( { overview: '' } ); - overview = false; dom.wrapper.classList.remove( 'overview' ); @@ -1811,6 +1808,8 @@ transformElement( background, '' ); } ); + transformSlides( { overview: '' } ); + slide( indexh, indexv ); layout(); @@ -2053,7 +2052,7 @@ document.documentElement.classList.remove( stateBefore.pop() ); } - // If the overview is active, re-activate it to update positions + // Update the overview if it's currently active if( isOverview() ) { updateOverview(); }