Last active
August 30, 2018 15:10
-
-
Save Mr0grog/8740956 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Transition helper that allows elements to transition from | |
* scalar sizes (e.g. "2em") to "auto" (or vice versa). This is useful because | |
* browsers either simply do not animate such transitions or do them poorly. | |
* | |
* Requires your CSS to already have the transition defined. This just allows | |
* it to function without much jankiness. | |
* | |
* Usage: | |
* | |
* doTransition( someElement ) | |
* .properties( "width", "height" ) | |
* .to( function( element ) { | |
* element.className = "css for the destination state"; | |
* }); | |
* | |
* 1. Set it up by calling `transition` with the element you are animating. | |
* 2. Call `properties` on the result of that call with the name of the | |
* properties that will animate. | |
* 3. Call `to` with a function that will move things to the end state of the | |
* animation. This helper will call it at the right time. | |
*/ | |
var doTransition = (function( undefined ) { | |
var el = document.createElement( "fake" ), | |
transitions = { | |
"transition": "transitionend", | |
"OTransition": "otransitionend", | |
"MSTransition": "msTransitionEnd", | |
"MozTransition": "transitionend", | |
"WebkitTransition": "webkitTransitionEnd" | |
}, | |
transitionProperty, | |
transitionEvent; | |
for ( var type in transitions ){ | |
if ( el.style[ type ] !== undefined ) { | |
transitionProperty = type; | |
transitionEvent = transitions[ type ]; | |
break; | |
} | |
} | |
function doTransition( element, properties ) { | |
properties = [].slice.call( arguments, 1 ); | |
var start, end; | |
return { | |
// add properties to animate | |
properties: function( property ) { | |
properties = properties.concat( [].slice.call( arguments ) ); | |
return this; | |
}, | |
// Declare the end state we are transitioning to. Optionally pass | |
// a `this` parameter to be used when calling the callback. | |
to: function to( goToEndState, context ) { | |
if ( !transitionEvent ) { | |
goToEndState.call( context, element ); | |
return; | |
} | |
// Measure the starting dimensions | |
start = properties.reduce( function( start, property ) { | |
start[ property ] = getComputedStyle( element )[ property ]; | |
return start; | |
}, {} ); | |
// suppress animation, move to end state, and re-measure | |
element.style[ transitionProperty ] = "none"; | |
goToEndState.call( context, element ); | |
end = properties.reduce( function( end, property ) { | |
end[ property ] = getComputedStyle( element )[ property ]; | |
return end; | |
}, {} ); | |
// Manually reset animating properties to the start state | |
properties.forEach( function( property ) { | |
element.style[ property ] = start[ property ]; | |
}); | |
element.offsetLeft; | |
// Now turn on animation again and animate to the end state | |
element.style[ transitionProperty ] = ""; | |
properties.forEach( function( property ) { | |
element.style[ property ] = end[ property ]; | |
}); | |
// When transitions are done, remove manually set styles | |
element.addEventListener( transitionEvent, function endTransition( event ) { | |
if ( event.target === element ) { | |
element.removeEventListener( transitionEvent, endTransition ); | |
element.style[ transitionProperty ] = "none"; | |
properties.forEach( function( property ) { | |
element.style[ property ] = ""; | |
}); | |
element.offsetLeft; | |
element.style[ transitionProperty ] = ""; | |
} | |
}) | |
} | |
}; | |
} | |
return doTransition; | |
}()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment