aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--css/reveal.css9
-rw-r--r--css/reveal.scss12
-rw-r--r--js/reveal.js81
-rw-r--r--test/examples/auto-animate.html2
4 files changed, 94 insertions, 10 deletions
diff --git a/css/reveal.css b/css/reveal.css
index a98a752..2d19d61 100644
--- a/css/reveal.css
+++ b/css/reveal.css
@@ -1227,6 +1227,15 @@ body {
transition-duration: 1200ms; }
/*********************************************
+ * AUTO ANIMATE
+ *********************************************/
+.reveal section[data-auto-animate] [data-auto-animate-unmatched="fade-in"] {
+ opacity: 0; }
+
+.reveal section[data-auto-animate="running"] [data-auto-animate-unmatched="fade-in"] {
+ opacity: 1; }
+
+/*********************************************
* OVERVIEW
*********************************************/
.reveal.overview {
diff --git a/css/reveal.scss b/css/reveal.scss
index 335b96b..1d14a02 100644
--- a/css/reveal.scss
+++ b/css/reveal.scss
@@ -1311,6 +1311,18 @@ $controlsArrowAngleActive: 36deg;
/*********************************************
+ * AUTO ANIMATE
+ *********************************************/
+
+.reveal section[data-auto-animate] [data-auto-animate-unmatched="fade-in"] {
+ opacity: 0;
+}
+.reveal section[data-auto-animate="running"] [data-auto-animate-unmatched="fade-in"] {
+ opacity: 1;
+}
+
+
+/*********************************************
* OVERVIEW
*********************************************/
diff --git a/js/reveal.js b/js/reveal.js
index 1bb9842..765ce3d 100644
--- a/js/reveal.js
+++ b/js/reveal.js
@@ -1431,9 +1431,8 @@
toArray( dom.slides.querySelectorAll( '[data-auto-animate]:not([data-auto-animate=""])' ) ).forEach( function( element ) {
element.dataset.autoAnimate = '';
} );
- toArray( dom.wrapper.querySelectorAll( '[data-auto-animate-target]' ) ).forEach( function( element ) {
- delete element.dataset.autoAnimateTarget;
- } );
+
+ removeEphemeralAutoAnimateAttributes();
if( autoAnimateStyleSheet && autoAnimateStyleSheet.parentNode ) {
autoAnimateStyleSheet.parentNode.removeChild( autoAnimateStyleSheet );
@@ -3849,10 +3848,8 @@
autoAnimateStyleSheet.innerHTML = '';
}
- // Clean up from previous animations
- toArray( document.querySelectorAll( '[data-auto-animate-target]' ) ).forEach( function( element ) {
- delete element.dataset.autoAnimateTarget;
- } );
+ // Clean up after prior animations
+ removeEphemeralAutoAnimateAttributes();
var slideOptions = getAutoAnimateOptions( toSlide, {
@@ -3868,9 +3865,21 @@
toSlide.dataset.autoAnimate = 'pending';
// Inject our auto-animate styles for this transition
- autoAnimateStyleSheet.innerHTML = getAutoAnimatableElements( fromSlide, toSlide ).map( function( elements ) {
+ var css = getAutoAnimatableElements( fromSlide, toSlide ).map( function( elements ) {
return getAutoAnimateCSS( elements.from, elements.to, elements.options || {}, slideOptions, autoAnimateCounter++ );
- } ).join( '' );
+ } );
+
+ // If the slide is configured to animate unmatched elements we
+ // need to flag them
+ if( toSlide.dataset.autoAnimateUnmatched ) {
+ getUnmatchedAutoAnimateElements( toSlide ).forEach( function( unmatchedElement ) {
+ unmatchedElement.dataset.autoAnimateUnmatched = 'fade-in';
+ } );
+
+ css.push( '.reveal [data-auto-animate="running"] [data-auto-animate-unmatched] { transition: all '+ (slideOptions.duration*0.8) +'s ease '+ (slideOptions.duration*0.2) +'s; }' );
+ }
+
+ autoAnimateStyleSheet.innerHTML = css.join( '' );
// Start the animation next cycle
requestAnimationFrame( function() {
@@ -3880,6 +3889,22 @@
}
/**
+ * Removes all attributes that we temporarily add to slide
+ * elements in order to carry out auto-animation.
+ */
+ function removeEphemeralAutoAnimateAttributes() {
+
+ toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ':not(.stack) [data-auto-animate-target]' ) ).forEach( function( element ) {
+ delete element.dataset.autoAnimateTarget;
+ } );
+
+ toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ':not(.stack) [data-auto-animate-unmatched]' ) ).forEach( function( element ) {
+ delete element.dataset.autoAnimateUnmatched;
+ } );
+
+ }
+
+ /**
* Auto-animates the properties of an element from their original
* values to their new state.
*
@@ -4140,6 +4165,44 @@
}
/**
+ * Returns a all elements within the given scope that should
+ * be considered unmatched in an auto-animate transition. If
+ * fading of unmatched elements is turnded on, these elements
+ * will fade when going between auto-aniamted slides.
+ *
+ * Note that parents of auto-animate targets are NOT considerd
+ * unmatched since fading them would break the auto-animation.
+ *
+ * @param {HTMLElement} rootElement
+ * @return {Array}
+ */
+ function getUnmatchedAutoAnimateElements( rootElement ) {
+
+ return [].slice.call( rootElement.children ).reduce( function( result, element ) {
+
+ // If the element is auto-animated we can stop looking at this tree
+ if( !element.hasAttribute( 'data-auto-animate-target' ) ) {
+
+ // If this element contains an auto-animated element it's considered
+ // a match since we can't fade it without affecting the inner
+ // auto-animate target
+ if( !element.querySelector( '[data-auto-animate-target]' ) ) {
+ result.push( element );
+ }
+ else {
+ // Keep looking down this tree
+ result = result.concat( getUnmatchedAutoAnimateElements( element ) );
+ }
+
+ }
+
+ return result;
+
+ }, [] );
+
+ }
+
+ /**
* Should the given element be preloaded?
* Decides based on local element attributes and global config.
*
diff --git a/test/examples/auto-animate.html b/test/examples/auto-animate.html
index bb982f5..a70e2d2 100644
--- a/test/examples/auto-animate.html
+++ b/test/examples/auto-animate.html
@@ -19,7 +19,7 @@
<div class="slides">
- <section data-auto-animate>
+ <section data-auto-animate data-auto-animate-unmatched="fade">
<h3>Auto-Animate Example</h3>
<p>This will fade out</p>
<img src="assets/image1.png" style="height: 100px;">