auto-animate refactoring and optimization

master
Hakim El Hattab 2020-02-08 20:29:43 +01:00
parent e9cbfefcce
commit ed4cbdfd03
1 changed files with 61 additions and 57 deletions

View File

@ -202,19 +202,19 @@
// CSS styles that auto-animations will animate between // CSS styles that auto-animations will animate between
autoAnimateStyles: [ autoAnimateStyles: [
{ property: 'opacity' }, 'opacity',
{ property: 'color' }, 'color',
{ property: 'background-color' }, 'background-color',
{ property: 'padding' }, 'padding',
{ property: 'font-size' }, 'font-size',
{ property: 'line-height' }, 'line-height',
{ property: 'letter-spacing' }, 'letter-spacing',
{ property: 'border-width' }, 'border-width',
{ property: 'border-color' }, 'border-color',
{ property: 'border-top-left-radius' }, 'border-top-left-radius',
{ property: 'border-top-right-radius' }, 'border-top-right-radius',
{ property: 'border-bottom-left-radius' }, 'border-bottom-left-radius',
{ property: 'border-bottom-right-radius' } 'border-bottom-right-radius'
], ],
// Controls automatic progression to the next slide // Controls automatic progression to the next slide
@ -1428,11 +1428,11 @@
} }
// Reset all auto animated elements // Reset all auto animated elements
toArray( dom.wrapper.querySelectorAll( '.slides .auto-animate-start' ) ).forEach( function( element ) { toArray( dom.slides.querySelectorAll( '[data-auto-animate]:not([data-auto-animate=""])' ) ).forEach( function( element ) {
element.classList.remove( 'auto-animate-start' ); element.dataset.autoAnimate = '';
} ); } );
toArray( dom.wrapper.querySelectorAll( '[data-auto-animate-target]' ) ).forEach( function( element ) { toArray( dom.wrapper.querySelectorAll( '[data-auto-animate-target]' ) ).forEach( function( element ) {
element.removeAttribute( 'data-auto-animate-target' ); delete element.dataset.autoAnimateTarget;
} ); } );
if( autoAnimateStyleSheet && autoAnimateStyleSheet.parentNode ) { if( autoAnimateStyleSheet && autoAnimateStyleSheet.parentNode ) {
@ -3045,22 +3045,22 @@
cueAutoSlide(); cueAutoSlide();
// Auto-animation // Auto-animation
if( config.autoAnimate && slideChanged && previousSlide && currentSlide ) { if( slideChanged && previousSlide && currentSlide ) {
// Skip the slide transition between our two slides // Skip the slide transition between our two slides
// when auto-animating individual elements // when auto-animating individual elements
if( previousSlide.hasAttribute( 'data-auto-animate' ) && currentSlide.hasAttribute( 'data-auto-animate' ) ) { if( previousSlide.hasAttribute( 'data-auto-animate' ) && currentSlide.hasAttribute( 'data-auto-animate' ) ) {
previousSlide.style.transition = 'none'; dom.slides.classList.add( 'disable-slide-transitions' );
currentSlide.style.transition = 'none';
setTimeout( function() { setTimeout( function() {
if( previousSlide ) previousSlide.style.transition = ''; dom.slides.classList.remove( 'disable-slide-transitions' );
if( currentSlide ) currentSlide.style.transition = '';
}, 0 ); }, 0 );
} }
// Run the auto-animation between our slides if( config.autoAnimate ) {
autoAnimate( previousSlide, currentSlide ); // Run the auto-animation between our slides
autoAnimate( previousSlide, currentSlide );
}
} }
@ -3863,33 +3863,33 @@
} }
// Check if easing is overriden // Check if easing is overriden
if( toSlide.hasAttribute( 'data-auto-animate-easing' ) ) { if( toSlide.dataset.autoAnimateEasing ) {
animationOptions.easing = toSlide.getAttribute( 'data-auto-animate-easing' ); animationOptions.easing = toSlide.dataset.autoAnimateEasing;
} }
// Check if the duration is overriden // Check if the duration is overriden
if( toSlide.hasAttribute( 'data-auto-animate-duration' ) ) { if( toSlide.dataset.autoAnimateDuration ) {
animationOptions.duration = parseFloat( toSlide.getAttribute( 'data-auto-animate-duration' ) ); animationOptions.duration = parseFloat( toSlide.dataset.autoAnimateDuration );
} }
// Remove any existing animate-target IDs to keep the DOM clean // 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 ) {
element.removeAttribute( 'data-auto-animate-target' ); delete element.dataset.autoAnimateTarget;
} ); } );
// Reset any prior animation // Set out starting state
fromSlide.classList.remove( 'auto-animate-start' ); fromSlide.dataset.autoAnimate = 'pending';
toSlide.classList.remove( 'auto-animate-start' ); toSlide.dataset.autoAnimate = 'pending';
// Generate and write out custom auto-animate styles to the DOM // Generate and write out custom auto-animate styles to the DOM
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( '' );
// Start the animation next cycle // Start the animation next cycle
setTimeout( function() { requestAnimationFrame( function() {
toSlide.classList.add( 'auto-animate-start' ); toSlide.dataset.autoAnimate = 'running';
}, 0 ); } );
} }
@ -3908,17 +3908,17 @@
function getAutoAnimateCSS( from, to, options, animationOptions, id ) { function getAutoAnimateCSS( from, to, options, animationOptions, id ) {
// Each element gets a unique auto-animate ID // Each element gets a unique auto-animate ID
from.setAttribute( 'data-auto-animate-target', '' ); from.dataset.autoAnimateTarget = '';
to.setAttribute( 'data-auto-animate-target', id ); to.dataset.autoAnimateTarget = id;
var fromProps = getAutoAnimatableProperties( 'from', from, options ), var fromProps = getAutoAnimatableProperties( 'from', from, options ),
toProps = getAutoAnimatableProperties( 'to', to, options ); toProps = getAutoAnimatableProperties( 'to', to, options );
// Instantly move to the 'from' state // Instantly move to the 'from' state
fromProps.styles.push([ 'transition', 'none' ]); fromProps.styles['transition'] = 'none';
// transition to the 'to' state // transition to the 'to' state
toProps.styles.push([ 'transition', 'all '+ animationOptions.duration +'s '+ animationOptions.easing ]); toProps.styles['transition'] = 'all '+ animationOptions.duration +'s '+ animationOptions.easing;
// 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
@ -3937,25 +3937,30 @@
if( options.translate !== false ) transform.push( 'translate('+delta.x+'px, '+delta.y+'px)' ); if( options.translate !== false ) transform.push( 'translate('+delta.x+'px, '+delta.y+'px)' );
if( options.scale !== false ) transform.push( 'scale('+delta.scaleX+','+delta.scaleY+')' ); if( options.scale !== false ) transform.push( 'scale('+delta.scaleX+','+delta.scaleY+')' );
fromProps.styles.push([ 'transform', transform.join( ' ' ) ]); fromProps.styles['transform'] = transform.join( ' ' );
fromProps.styles.push([ 'transform-origin', 'top left' ]); fromProps.styles['transform-origin'] = 'top left';
toProps.styles.push([ 'transform', 'none' ]); toProps.styles['transform'] = 'none';
} }
// Build up our custom CSS. We need to override inline styles // Build up our custom CSS. We need to override inline styles
// so we need to make our styles vErY IMPORTANT!1!! // so we need to make our styles vErY IMPORTANT!1!!
var fromCSS = fromProps.styles.map( function( style ) { var fromCSS = Object.keys( fromProps.styles ).map( function( propertyName ) {
return style[0] + ': ' + style[1] + ' !important;'; return propertyName + ': ' + fromProps.styles[propertyName] + ' !important;';
} ).join( '' ); } ).join( '' );
var toCSS = toProps.styles.map( function( style ) { var toCSS = Object.keys( toProps.styles ).map( function( propertyName ) {
return style[0] + ': ' + style[1] + ' !important;'; if( toProps.styles[propertyName] !== fromProps.styles[propertyName] ) {
return propertyName + ': ' + toProps.styles[propertyName] + ' !important;';
}
else {
return '';
}
} ).join( '' ); } ).join( '' );
return '.reveal [data-auto-animate-target="'+ id +'"] {'+ fromCSS +'}' + return '.reveal [data-auto-animate] [data-auto-animate-target="'+ id +'"] {'+ fromCSS +'}' +
'.reveal .auto-animate-start [data-auto-animate-target="'+ id +'"] {'+ toCSS +'}'; '.reveal [data-auto-animate="running"] [data-auto-animate-target="'+ id +'"] {'+ toCSS +'}';
} }
@ -3976,12 +3981,16 @@
properties.height = element.offsetHeight; properties.height = element.offsetHeight;
} }
var computedStyles; var computedStyles = window.getComputedStyle( element );
// CSS styles // CSS styles
( options.styles || config.autoAnimateStyles ).forEach( function( style ) { ( options.styles || config.autoAnimateStyles ).forEach( function( style ) {
var value; var value;
// `style` is either the property name directly, or an object
// definition of a style property
if( typeof style === 'string' ) style = { property: style };
if( typeof style.from !== 'undefined' && direction === 'from' ) { if( typeof style.from !== 'undefined' && direction === 'from' ) {
value = style.from; value = style.from;
} }
@ -3989,16 +3998,11 @@
value = style.to; value = style.to;
} }
else { else {
value = element.style[style.property]; value = computedStyles[style.property];
if( value === '' ) {
computedStyles = computedStyles || window.getComputedStyle( element );
value = computedStyles[style.property];
}
} }
if( value !== '' ) { if( value !== '' ) {
properties.styles.push([ style.property, value ]); properties.styles[style.property] = value;
} }
} ); } );