make it possible to override auto-anim properties per-element

This commit is contained in:
Hakim El Hattab 2020-02-09 09:28:34 +01:00
parent e45626d6bd
commit 1c62b808ad
2 changed files with 60 additions and 38 deletions

View File

@ -3849,39 +3849,23 @@
autoAnimateStyleSheet.innerHTML = ''; autoAnimateStyleSheet.innerHTML = '';
} }
var animationOptions = { // Clean up from previous animations
easing: config.autoAnimateEasing,
duration: config.autoAnimateDuration,
offsetY: 0
};
// If our slides are centered vertically, we need to
// account for their difference in position when
// calculating deltas for animated elements
if( config.center ) {
animationOptions.offsetY = fromSlide.offsetTop - toSlide.offsetTop;
}
// Check if easing is overriden
if( toSlide.dataset.autoAnimateEasing ) {
animationOptions.easing = toSlide.dataset.autoAnimateEasing;
}
// Check if the duration is overriden
if( toSlide.dataset.autoAnimateDuration ) {
animationOptions.duration = parseFloat( toSlide.dataset.autoAnimateDuration );
}
// Clean up from previous animations to avoid polluting the DOM
toArray( document.querySelectorAll( '[data-auto-animate-target]' ) ).forEach( function( element ) { toArray( document.querySelectorAll( '[data-auto-animate-target]' ) ).forEach( function( element ) {
delete element.dataset.autoAnimateTarget; delete element.dataset.autoAnimateTarget;
} ); } );
// Set out starting state var animationOptions = getAutoAnimateOptions( toSlide );
// If our slides are centered vertically, we need to
// account for their difference in position when
// calculating deltas for animated elements
if( config.center ) animationOptions.offsetY = fromSlide.offsetTop - toSlide.offsetTop;
// Set our starting state
fromSlide.dataset.autoAnimate = 'pending'; fromSlide.dataset.autoAnimate = 'pending';
toSlide.dataset.autoAnimate = 'pending'; toSlide.dataset.autoAnimate = 'pending';
// Generate and write out custom auto-animate styles to the DOM // Inject our auto-animate styles for this transition
autoAnimateStyleSheet.innerHTML = getAutoAnimatableElements( fromSlide, toSlide ).map( function( elements ) { autoAnimateStyleSheet.innerHTML = getAutoAnimatableElements( fromSlide, toSlide ).map( function( elements ) {
return getAutoAnimateCSS( elements[0], elements[1], elements[2] || {}, animationOptions, autoAnimateCounter++ ); return getAutoAnimateCSS( elements[0], elements[1], elements[2] || {}, animationOptions, autoAnimateCounter++ );
} ).join( '' ); } ).join( '' );
@ -3893,37 +3877,75 @@
} }
/**
* Returns the auto-animate options for the given element.
*
* @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
*/
function getAutoAnimateOptions( element, inheritOptions ) {
var options = {
easing: config.autoAnimateEasing,
duration: config.autoAnimateDuration,
delay: 0
};
if( inheritOptions ) extend( options, inheritOptions );
if( element.dataset.autoAnimateEasing ) {
options.easing = element.dataset.autoAnimateEasing;
}
if( element.dataset.autoAnimateDuration ) {
options.duration = parseFloat( element.dataset.autoAnimateDuration );
}
if( element.dataset.autoAnimateDelay ) {
options.delay = parseFloat( element.dataset.autoAnimateDelay );
}
return options;
}
/** /**
* Auto-animates the properties of an element from their original * Auto-animates the properties of an element from their original
* values to their new state. * values to their new state.
* *
* @param {HTMLElement} from * @param {HTMLElement} from
* @param {HTMLElement} to * @param {HTMLElement} to
* @param {Object} options Optional settings for this specific pair * @param {Object} elementOptions Options for this element pair
* @param {Object} animationOptions Options that apply to all * @param {Object} animationOptions Options for all elements in
* elements in this transition
* @param {String} id Unique ID that we can use to identify this * @param {String} id Unique ID that we can use to identify this
* auto-animate element in the DOM * auto-animate element in the DOM
*/ */
function getAutoAnimateCSS( from, to, options, animationOptions, id ) { function getAutoAnimateCSS( from, to, elementOptions, animationOptions, id ) {
// Each element gets a unique auto-animate ID // 'from' elements are given a data-auto-animate-target with no value,
// 'to' elements are are given a data-auto-animate-target with an ID
from.dataset.autoAnimateTarget = ''; from.dataset.autoAnimateTarget = '';
to.dataset.autoAnimateTarget = id; to.dataset.autoAnimateTarget = id;
var fromProps = getAutoAnimatableProperties( 'from', from, options ), // Each element may override any of the auto-animate options
toProps = getAutoAnimatableProperties( 'to', to, options ); // like transition easing, duration and delay
animationOptions = getAutoAnimateOptions( to, animationOptions );
var fromProps = getAutoAnimatableProperties( 'from', from, elementOptions ),
toProps = getAutoAnimatableProperties( 'to', to, elementOptions );
// Instantly move to the 'from' state // Instantly move to the 'from' state
fromProps.styles['transition'] = 'none'; fromProps.styles['transition'] = 'none';
// transition to the 'to' state // transition to the 'to' state
toProps.styles['transition'] = 'all '+ animationOptions.duration +'s '+ animationOptions.easing; toProps.styles['transition'] = 'all '+ animationOptions.duration +'s '+ animationOptions.easing + ' ' + animationOptions.delay + 's';
// If translation and/or scalin are enabled, offset the // If translation and/or scalin are enabled, offset the
// 'to' element so that it starts out at the same position // 'to' element so that it starts out at the same position
// and scale as the 'from' element // and scale as the 'from' element
if( options.translate !== false || options.scale !== false ) { if( elementOptions.translate !== false || elementOptions.scale !== false ) {
var delta = { var delta = {
x: fromProps.x - toProps.x, x: fromProps.x - toProps.x,
@ -3934,8 +3956,8 @@
var transform = []; var transform = [];
if( options.translate !== false ) transform.push( 'translate('+delta.x+'px, '+delta.y+'px)' ); if( elementOptions.translate !== false ) transform.push( 'translate('+delta.x+'px, '+delta.y+'px)' );
if( options.scale !== false ) transform.push( 'scale('+delta.scaleX+','+delta.scaleY+')' ); if( elementOptions.scale !== false ) transform.push( 'scale('+delta.scaleX+','+delta.scaleY+')' );
fromProps.styles['transform'] = transform.join( ' ' ); fromProps.styles['transform'] = transform.join( ' ' );
fromProps.styles['transform-origin'] = 'top left'; fromProps.styles['transform-origin'] = 'top left';

View File

@ -30,7 +30,7 @@ function Example() {
</code></pre> </code></pre>
</section> </section>
<section data-auto-animate data-auto-animate-unmatched="fade"> <section data-auto-animate data-auto-animate-unmatched="fade">
<h3>Auto-Matched Content (no IDs)</h3> <h3 data-auto-animate-delay="1">Auto-Matched Content (no IDs)</h3>
<p style="opacity: 0.2; margin-top: 200px;">This will fade out</p> <p style="opacity: 0.2; margin-top: 200px;">This will fade out</p>
<p>This element is unmatched</p> <p>This element is unmatched</p>
<img src="assets/image1.png" style="height: 100px;"> <img src="assets/image1.png" style="height: 100px;">