From 1649bd0d98ef73b0019319637bd41c95a6b0c222 Mon Sep 17 00:00:00 2001
From: Hakim El Hattab <hakim.elhattab@gmail.com>
Date: Mon, 24 Feb 2020 15:45:44 +0100
Subject: [PATCH] auto-animate bug fixes + support for inheriting options from
 closest animated parent element

---
 css/reveal.css  |  2 +-
 css/reveal.scss |  2 +-
 js/reveal.js    | 65 +++++++++++++++++++++++++++++++++----------------
 3 files changed, 46 insertions(+), 23 deletions(-)

diff --git a/css/reveal.css b/css/reveal.css
index d4a8ccef..7af66ac7 100644
--- a/css/reveal.css
+++ b/css/reveal.css
@@ -1233,7 +1233,7 @@ body {
 /*********************************************
  * AUTO ANIMATE
  *********************************************/
-.reveal section[data-auto-animate]:not([data-auto-animate="running"]) [data-auto-animate-target="unmatched"] {
+.reveal section[data-auto-animate]:not(.stack):not([data-auto-animate="running"]) [data-auto-animate-target="unmatched"] {
   opacity: 0; }
 
 /*********************************************
diff --git a/css/reveal.scss b/css/reveal.scss
index 442338c5..51c7a9ec 100644
--- a/css/reveal.scss
+++ b/css/reveal.scss
@@ -1318,7 +1318,7 @@ $controlsArrowAngleActive: 36deg;
  * AUTO ANIMATE
  *********************************************/
 
-.reveal section[data-auto-animate]:not([data-auto-animate="running"]) [data-auto-animate-target="unmatched"] {
+.reveal section[data-auto-animate]:not(.stack):not([data-auto-animate="running"]) [data-auto-animate-target="unmatched"] {
 	opacity: 0;
 }
 
diff --git a/js/reveal.js b/js/reveal.js
index 71f5e275..08ecbf63 100644
--- a/js/reveal.js
+++ b/js/reveal.js
@@ -3886,7 +3886,7 @@
 					unmatchedElement.dataset.autoAnimateTarget = 'unmatched';
 				} );
 
-				css.push( '.reveal [data-auto-animate="running"] [data-auto-animate-target="unmatched"] { transition: all '+ (animationOptions.duration*0.8) +'s ease '+ (animationOptions.duration*0.2) +'s; }' );
+				css.push( '[data-auto-animate="running"] [data-auto-animate-target="unmatched"] { transition: all '+ (animationOptions.duration*0.8) +'s ease '+ (animationOptions.duration*0.2) +'s; }' );
 			}
 
 			// Setting the whole chunk of CSS at once is the most
@@ -3904,6 +3904,8 @@
 				}
 			} );
 
+			dispatchEvent( 'autoanimate', { fromSlide: fromSlide, toSlide: toSlide, sheet: autoAnimateStyleSheet } );
+
 		}
 
 	}
@@ -3914,7 +3916,7 @@
 	 */
 	function removeEphemeralAutoAnimateAttributes() {
 
-		toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ':not(.stack) [data-auto-animate-target]' ) ).forEach( function( element ) {
+		toArray( dom.wrapper.querySelectorAll( '[data-auto-animate-target]' ) ).forEach( function( element ) {
 			delete element.dataset.autoAnimateTarget;
 		} );
 
@@ -3956,28 +3958,31 @@
 		// of the 'from' element
 		if( elementOptions.translate !== false || elementOptions.scale !== false ) {
 
-			var scale = Reveal.getScale();
+			var presentationScale = Reveal.getScale();
 
 			var delta = {
-				x: ( fromProps.x - toProps.x ) / scale,
-				y: ( fromProps.y - toProps.y ) / scale,
+				x: ( fromProps.x - toProps.x ) / presentationScale,
+				y: ( fromProps.y - toProps.y ) / presentationScale,
 				scaleX: fromProps.width / toProps.width,
 				scaleY: fromProps.height / toProps.height
 			};
 
-			// Limit decimal points to avoid 0.00001px blur and stutter
-			delta.x = Math.round( delta.x * 100000 ) / 100000;
-			delta.y = Math.round( delta.y * 100000 ) / 100000;
-			delta.scaleX = Math.round( delta.scaleX * 100000 ) / 100000;
-			delta.scaleX = Math.round( delta.scaleX * 100000 ) / 100000;
+			// Limit decimal points to avoid 0.0001px blur and stutter
+			delta.x = Math.round( delta.x * 1000 ) / 1000;
+			delta.y = Math.round( delta.y * 1000 ) / 1000;
+			delta.scaleX = Math.round( delta.scaleX * 1000 ) / 1000;
+			delta.scaleX = Math.round( delta.scaleX * 1000 ) / 1000;
+
+			var translate = elementOptions.translate !== false && ( delta.x !== 0 || delta.y !== 0 ),
+				scale = elementOptions.scale !== false && ( delta.scaleX !== 0 || delta.scaleY !== 0 );
 
 			// No need to transform if nothing's changed
-			if( delta.x !== 0 || delta.y !== 0 || delta.scaleX !== 1 || delta.scaleY !== 1 ) {
+			if( translate || scale ) {
 
 				var transform = [];
 
-				if( elementOptions.translate !== false ) transform.push( 'translate('+delta.x+'px, '+delta.y+'px)' );
-				if( elementOptions.scale !== false ) transform.push( 'scale('+delta.scaleX+','+delta.scaleY+')' );
+				if( translate ) transform.push( 'translate('+delta.x+'px, '+delta.y+'px)' );
+				if( scale ) transform.push( 'scale('+delta.scaleX+','+delta.scaleY+')' );
 
 				fromProps.styles['transform'] = transform.join( ' ' );
 				fromProps.styles['transform-origin'] = 'top left';
@@ -4031,9 +4036,8 @@
 				return propertyName + ': ' + toProps.styles[propertyName] + ' !important;';
 			} ).join( '' );
 
-
-			css = 	'.reveal [data-auto-animate-target="'+ id +'"] {'+ fromCSS +'}' +
-					'.reveal [data-auto-animate="running"] [data-auto-animate-target="'+ id +'"] {'+ toCSS +'}';
+			css = 	'[data-auto-animate-target="'+ id +'"] {'+ fromCSS +'}' +
+					'[data-auto-animate="running"] [data-auto-animate-target="'+ id +'"] {'+ toCSS +'}';
 
 		}
 
@@ -4046,10 +4050,10 @@
 	 *
 	 * @param {HTMLElement} element Element to pick up options
 	 * from, either a slide or an animation target
-	 * @param {Object} [inheritOptions] optional set of options
-	 * to inherit as a base
+	 * @param {Object} [inheritedOptions] Optional set of existing
+	 * options
 	 */
-	function getAutoAnimateOptions( element, inheritOptions ) {
+	function getAutoAnimateOptions( element, inheritedOptions ) {
 
 		var options = {
 			easing: config.autoAnimateEasing,
@@ -4057,7 +4061,15 @@
 			delay: 0
 		};
 
-		if( inheritOptions ) extend( options, inheritOptions );
+		if( inheritedOptions ) options = extend( options, inheritedOptions );
+
+		// Inherit options from parent elements
+		if( element.closest && element.parentNode ) {
+			var autoAnimatedParent = element.parentNode.closest( '[data-auto-animate-target]' );
+			if( autoAnimatedParent ) {
+				options = getAutoAnimateOptions( autoAnimatedParent, options );
+			}
+		}
 
 		if( element.dataset.autoAnimateEasing ) {
 			options.easing = element.dataset.autoAnimateEasing;
@@ -4088,7 +4100,17 @@
 
 		// Position and size
 		if( elementOptions.translate !== false || elementOptions.scale !== false ) {
-			var bounds = element.getBoundingClientRect();
+			var bounds;
+
+			// Custom auto-animate may optionally return a custom tailored
+			// measurement function
+			if( typeof elementOptions.measure === 'function' ) {
+				bounds = elementOptions.measure( element );
+			}
+			else {
+				bounds = element.getBoundingClientRect();
+			}
+
 			properties.x = bounds.x;
 			properties.y = bounds.y;
 			properties.width = bounds.width;
@@ -6576,6 +6598,7 @@
 		getScale: function() {
 			return scale;
 		},
+
 		getComputedSlideSize: getComputedSlideSize,
 
 		// Returns the current configuration object
-- 
GitLab