diff --git a/css/reveal.css b/css/reveal.css index 051f0794..9967c2ae 100644 --- a/css/reveal.css +++ b/css/reveal.css @@ -188,6 +188,49 @@ body { /********************************************* * CONTROLS *********************************************/ +@-webkit-keyframes bounce-right { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateX(0); + transform: translateX(0); } + 20% { + -webkit-transform: translateX(10px); + transform: translateX(10px); } + 30% { + -webkit-transform: translateX(-5px); + transform: translateX(-5px); } } +@keyframes bounce-right { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateX(0); + transform: translateX(0); } + 20% { + -webkit-transform: translateX(10px); + transform: translateX(10px); } + 30% { + -webkit-transform: translateX(-5px); + transform: translateX(-5px); } } + +@-webkit-keyframes bounce-down { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateY(0); + transform: translateY(0); } + 20% { + -webkit-transform: translateY(10px); + transform: translateY(10px); } + 30% { + -webkit-transform: translateY(-5px); + transform: translateY(-5px); } } + +@keyframes bounce-down { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateY(0); + transform: translateY(0); } + 20% { + -webkit-transform: translateY(10px); + transform: translateY(10px); } + 30% { + -webkit-transform: translateY(-5px); + transform: translateY(-5px); } } + .reveal .controls { display: none; position: absolute; @@ -201,8 +244,6 @@ body { .reveal .controls button { position: absolute; padding: 0; - width: 46px; - height: 46px; background-color: transparent; border: 0; outline: 0; @@ -217,8 +258,8 @@ body { opacity: 0; -webkit-appearance: none; -webkit-tap-highlight-color: transparent; } - .reveal .controls button:before, - .reveal .controls button:after { + .reveal .controls .pagination-arrow:before, + .reveal .controls .pagination-arrow:after { content: ''; position: absolute; top: 0; @@ -231,44 +272,58 @@ body { -webkit-transform-origin: 3px 50%; transform-origin: 3px 50%; will-change: transform; } - .reveal .controls button:before { - -webkit-transform: translateX(7px) translateY(20px) rotate(44deg); - transform: translateX(7px) translateY(20px) rotate(44deg); } - .reveal .controls button:after { - -webkit-transform: translateX(7px) translateY(20px) rotate(-44deg); - transform: translateX(7px) translateY(20px) rotate(-44deg); } - .reveal .controls button:hover:before { - -webkit-transform: translateX(7px) translateY(20px) rotate(40deg); - transform: translateX(7px) translateY(20px) rotate(40deg); } - .reveal .controls button:hover:after { - -webkit-transform: translateX(7px) translateY(20px) rotate(-40deg); - transform: translateX(7px) translateY(20px) rotate(-40deg); } - .reveal .controls button:active:before { - -webkit-transform: translateX(7px) translateY(20px) rotate(36deg); - transform: translateX(7px) translateY(20px) rotate(36deg); } - .reveal .controls button:active:after { - -webkit-transform: translateX(7px) translateY(20px) rotate(-36deg); - transform: translateX(7px) translateY(20px) rotate(-36deg); } + .reveal .controls .pagination-arrow { + position: relative; + width: 46px; + height: 46px; } + .reveal .controls .pagination-arrow:before { + -webkit-transform: translateX(7px) translateY(20px) rotate(44deg); + transform: translateX(7px) translateY(20px) rotate(44deg); } + .reveal .controls .pagination-arrow:after { + -webkit-transform: translateX(7px) translateY(20px) rotate(-44deg); + transform: translateX(7px) translateY(20px) rotate(-44deg); } + .reveal .controls .pagination-arrow:hover:before { + -webkit-transform: translateX(7px) translateY(20px) rotate(40deg); + transform: translateX(7px) translateY(20px) rotate(40deg); } + .reveal .controls .pagination-arrow:hover:after { + -webkit-transform: translateX(7px) translateY(20px) rotate(-40deg); + transform: translateX(7px) translateY(20px) rotate(-40deg); } + .reveal .controls .pagination-arrow:active:before { + -webkit-transform: translateX(7px) translateY(20px) rotate(36deg); + transform: translateX(7px) translateY(20px) rotate(36deg); } + .reveal .controls .pagination-arrow:active:after { + -webkit-transform: translateX(7px) translateY(20px) rotate(-36deg); + transform: translateX(7px) translateY(20px) rotate(-36deg); } .reveal .controls .navigate-left { right: 82px; - bottom: 18px; - -webkit-transform: translateY(-50%); - transform: translateY(-50%); } + bottom: 18px; } + .reveal .controls .navigate-left .pagination-arrow { + -webkit-transform: translateY(-50%); + transform: translateY(-50%); } .reveal .controls .navigate-right { right: 0; - bottom: 18px; - -webkit-transform: translateY(-50%) rotate(180deg); - transform: translateY(-50%) rotate(180deg); } + bottom: 18px; } + .reveal .controls .navigate-right .pagination-arrow { + -webkit-transform: translateY(-50%) rotate(180deg); + transform: translateY(-50%) rotate(180deg); } + .reveal .controls .navigate-right.bounce { + -webkit-animation: bounce-right 2s 50 both ease-out; + animation: bounce-right 2s 50 both ease-out; } .reveal .controls .navigate-up { right: 18px; - bottom: 82px; - -webkit-transform: translateX(-50%) rotate(90deg); - transform: translateX(-50%) rotate(90deg); } + bottom: 82px; } + .reveal .controls .navigate-up .pagination-arrow { + -webkit-transform: translateX(-50%) rotate(90deg); + transform: translateX(-50%) rotate(90deg); } .reveal .controls .navigate-down { right: 18px; - bottom: 0; - -webkit-transform: translateX(-50%) rotate(-90deg); - transform: translateX(-50%) rotate(-90deg); } + bottom: 0; } + .reveal .controls .navigate-down .pagination-arrow { + -webkit-transform: translateX(-50%) rotate(-90deg); + transform: translateX(-50%) rotate(-90deg); } + .reveal .controls .navigate-down.bounce { + -webkit-animation: bounce-down 2s 50 both ease-out; + animation: bounce-down 2s 50 both ease-out; } .reveal .controls[data-controls-back-arrows="faded"] .navigate-left.enabled, .reveal .controls[data-controls-back-arrows="faded"] .navigate-up.enabled { opacity: 0.3; } @@ -321,12 +376,12 @@ body { .reveal:not(.has-horizontal-slides) .controls .navigate-down { right: 0; } -.reveal.has-dark-background .controls button:after, -.reveal.has-dark-background .controls button:before { +.reveal.has-dark-background .controls .pagination-arrow:after, +.reveal.has-dark-background .controls .pagination-arrow:before { background-color: #fff; } -.reveal.has-light-background .controls button:after, -.reveal.has-light-background .controls button:before { +.reveal.has-light-background .controls .pagination-arrow:after, +.reveal.has-light-background .controls .pagination-arrow:before { background-color: #000; } /********************************************* diff --git a/css/reveal.scss b/css/reveal.scss index 8785d4af..6209486b 100644 --- a/css/reveal.scss +++ b/css/reveal.scss @@ -235,6 +235,18 @@ body { * CONTROLS *********************************************/ +@keyframes bounce-right { + 0%, 10%, 25%, 40%, 50% {transform: translateX(0);} + 20% {transform: translateX(10px);} + 30% {transform: translateX(-5px);} +} + +@keyframes bounce-down { + 0%, 10%, 25%, 40%, 50% {transform: translateY(0);} + 20% {transform: translateY(10px);} + 30% {transform: translateY(-5px);} +} + .reveal .controls { $size: 46px; $length: floor($size * 0.7); @@ -268,8 +280,6 @@ body { button { position: absolute; padding: 0; - width: $size; - height: $size; background-color: transparent; border: 0; outline: 0; @@ -287,8 +297,8 @@ body { -webkit-tap-highlight-color: rgba( 0, 0, 0, 0 ); } - button:before, - button:after { + .pagination-arrow:before, + .pagination-arrow:after { content: ''; position: absolute; top: 0; @@ -303,7 +313,11 @@ body { will-change: transform; } - button { + .pagination-arrow { + position: relative; + width: $size; + height: $size; + @include arrowTransform( $angle ); &:hover { @@ -318,25 +332,45 @@ body { .navigate-left { right: $size + $innerSpacing*2; bottom: $innerSpacing; - transform: translateY(-50%); + + .pagination-arrow { + transform: translateY(-50%); + } } .navigate-right { right: 0; bottom: $innerSpacing; - transform: translateY(-50%) rotate( 180deg ); + + .pagination-arrow { + transform: translateY(-50%) rotate( 180deg ); + } + + &.bounce { + animation: bounce-right 2s 50 both ease-out; + } } .navigate-up { right: $innerSpacing; bottom: $size + $innerSpacing*2; - transform: translateX(-50%) rotate( 90deg ); + + .pagination-arrow { + transform: translateX(-50%) rotate( 90deg ); + } } .navigate-down { right: $innerSpacing; bottom: 0; - transform: translateX(-50%) rotate( -90deg ); + + .pagination-arrow { + transform: translateX(-50%) rotate( -90deg ); + } + + &.bounce { + animation: bounce-down 2s 50 both ease-out; + } } // Back arrow style: "faded": @@ -432,13 +466,13 @@ body { right: 0; } -.reveal.has-dark-background .controls button:after, -.reveal.has-dark-background .controls button:before { +.reveal.has-dark-background .controls .pagination-arrow:after, +.reveal.has-dark-background .controls .pagination-arrow:before { background-color: #fff; } -.reveal.has-light-background .controls button:after, -.reveal.has-light-background .controls button:before { +.reveal.has-light-background .controls .pagination-arrow:after, +.reveal.has-light-background .controls .pagination-arrow:before { background-color: #000; } diff --git a/js/reveal.js b/js/reveal.js index 42c38223..d39e2886 100644 --- a/js/reveal.js +++ b/js/reveal.js @@ -52,11 +52,15 @@ // Display controls in the bottom right corner controls: true, + // Hint at where the user can navigate, for example by animating + // the down arrow when we first encounter a vertical slide + controlsHints: true, + // Determines where controls appear, "edges" or "bottom-right" controlsLayout: 'bottom-right', - // Specifies the display rules for backwards navigation arrows; - // "faded", "hidden" or "visible" + // Visibility rule for backwards navigation arrows; "faded", "hidden" + // or "visible" controlsBackArrows: 'faded', // Display a presentation progress bar @@ -214,6 +218,10 @@ previousBackground, + // Remember which directions that the user has navigated towards + hasNavigatedRight = false, + hasNavigatedDown = false, + // Slides may hold a data-state attribute which we pick up and apply // as a class to the body. This list contains the combined state of // all current slides. @@ -524,10 +532,10 @@ // Arrow controls dom.controls = createSingletonNode( dom.wrapper, 'aside', 'controls', - '' + - '' + - '' + - '' ); + '' + + '' + + '' + + '' ); // Slide number dom.slideNumber = createSingletonNode( dom.wrapper, 'div', 'slide-number', '' ); @@ -550,6 +558,10 @@ dom.controlsPrev = toArray( document.querySelectorAll( '.navigate-prev' ) ); dom.controlsNext = toArray( document.querySelectorAll( '.navigate-next' ) ); + // The right and down arrows in the standard reveal.js controls + dom.controlsRightArrow = dom.controls.querySelector( '.navigate-right' ); + dom.controlsDownArrow = dom.controls.querySelector( '.navigate-down' ); + dom.statusDiv = createStatusDiv(); } @@ -2905,6 +2917,26 @@ } + if( config.controlsHints ) { + + // Highlight control arrows with an animation to ensure + // that the viewer knows how to navigate + if( !hasNavigatedDown && routes.down ) { + dom.controlsDownArrow.classList.add( 'highlight' ); + } + else { + dom.controlsDownArrow.classList.remove( 'highlight' ); + + if( !hasNavigatedRight && routes.right && indexh === 0 ) { + dom.controlsRightArrow.classList.add( 'highlight' ); + } + else { + dom.controlsRightArrow.classList.remove( 'highlight' ); + } + } + + } + } /** @@ -4157,6 +4189,8 @@ function navigateRight() { + hasNavigatedRight = true; + // Reverse for RTL if( config.rtl ) { if( ( isOverview() || previousFragment() === false ) && availableRoutes().right ) { @@ -4181,6 +4215,8 @@ function navigateDown() { + hasNavigatedDown = true; + // Prioritize revealing fragments if( ( isOverview() || nextFragment() === false ) && availableRoutes().down ) { slide( indexh, indexv + 1 ); @@ -4227,6 +4263,9 @@ */ function navigateNext() { + hasNavigatedRight = true; + hasNavigatedDown = true; + // Prioritize revealing fragments if( nextFragment() === false ) { if( availableRoutes().down ) {