Closed rstacruz closed 7 years ago
Not to my knowledge. Would definitely make sense to have a plugin that did that. I'm slightly less optimistic about how easy it'd be - the plugin would have to know whether an animation had been defined in CSS, whether there was a valid @keyframes
declaration, and whether CSS animations are supported in the current environment - but I would love to be proven wrong!
Here's a simple version - http://jsfiddle.net/rich_harris/QmR33/. Here's the exact same thing, but without a @keyframes
declaration - it all falls apart, because it's listening for an event that never happens. Would be great if there was a way to work around that issue.
The way I thought of implementing this was to have a timeout. In pseudo-code:
teardown = _.once(function() { ... });
node.on('animationend', teardown);
setTimeout(teardown, 1000);
Not exactly the best way to handle it, but I've yet to find a way to detect if animations are ongoing. (I imagine it's possible though through some hackery, but I'd avoid things that would unnecessarily do DOM layout thrashing.)
For [webkit]AnimationEnd, you need to guard the event with if(e.target!=node) { return }
as it will fire for child nodes, for transitionEnd
it only fires on the transitioned node.
@martypdx wow. Only one possible response to that
@Rich-Harris haha yeah, it was fun figuring that out. If it helps anyone, here's some code I wrote a couple of years ago using jQuery (webkit only). I tried to come up with names for the different variations (transition, animation, leave class, remove class), but I just ended up having to look into the code to figure out what each one meant. I like the idea of a more generic "just works"
function changeFn(type, removeClass){
var eventName = 'webkit' + type + 'End'
return function(className, delegate, cb){
if( typeof delegate === 'function'){
cb = delegate
delegate = this
}
if(!delegate.nodeType) { delegate = delegate[0] }
var $this = $(this)
.addClass(className)
.on(eventName, function(e){
if(e.target!=delegate) { return }
$this.off(eventName)
if(removeClass) { $this.removeClass(className) }
cb()
} )
}
}
$.fn.segue = changeFn('Transition' , true)
$.fn.transition = changeFn('Transition', false)
$.fn.bridge = changeFn('Animation', true)
$.fn.animation = changeFn('Animation', false)
Here's a quick animate.css transition wrapper... (requires animate.css)
(function ( global, factory ) {
'use strict';
// Common JS (i.e. browserify) environment
if ( typeof module !== 'undefined' && module.exports && typeof require === 'function' ) {
factory( require( 'ractive' ) );
}
// AMD?
else if ( typeof define === 'function' && define.amd ) {
define([ 'ractive' ], factory );
}
// browser global
else if ( global.Ractive ) {
factory( global.Ractive );
}
else {
throw new Error( 'Could not find Ractive! It must be loaded before the ractive.transitions.animatecss plugin' );
}
}( typeof window !== 'undefined' ? window : this, function ( Ractive ) {
'use strict';
var ANIMATION_END_EVENT = (function(){
var eventName,
ANIMATION_END_EVENT_NAMES = {
'animation': 'animationend',
'-o-animation': 'oAnimationEnd',
'-moz-animation': 'animationend',
'-webkit-animation': 'webkitAnimationEnd',
'-ms-animation': 'animationend'
},
fakeEl = document.createElement('fakeelement');
for (eventName in ANIMATION_END_EVENT_NAMES) {
if (typeof(fakeEl.style[eventName]) !== 'undefined') {
return ANIMATION_END_EVENT_NAMES[eventName];
}
}
return null;
})();
var animateCSS = function ( t, transition ) {
// Process parameters. No error checking for non-existing transitions(!!)
transition = transition || (t.isIntro ? Ractive.transitions.animatecss.defaultIntro : Ractive.transitions.animatecss.defaultOutro);
// add 'animated' class if not present
if(!t.node.classList.contains('animated')) t.node.classList.add('animated');
// add the transition class, the transitions starts immediately
t.node.classList.add(transition);
// After the animation has ended, call `t.complete()` to signal that we've finished
t.node.addEventListener(ANIMATION_END_EVENT,function(){
t.node.classList.remove(transition);
t.complete();
});
};
Ractive.transitions.animatecss = animateCSS;
Ractive.transitions.animatecss.defaultIntro = 'slideInDown';
Ractive.transitions.animatecss.defaultOutro = 'slideOutUp';
}));
usage:
<div intro="animatecss:fadeIn" outro="animatecss:fadeOut">woosh</div>
Allthough fun to use, we've moved on to using velocity.js' UI pack for transitions (feels better to not rely on transitionend really, and it's actually smaller in size than animate.css, which is quite large). Will try to get it up to speed with the latest velocity.js UI pack changes tomorrow and post back :)
@cfenzo: I'm actually interested in building (or having someone else build) a Velocity plugin for Ractive.... As a new (and proud!) Ractive user, I'd like to make this happen in the next few weeks.
@julianshapiro: interesting.. There's probably more use cases for velocity+Ractive than transitions only tho.. right? :)
What we've done in the project where we're using it now, is having a small wrapper push the whole UI pack as custom transitions, so you can do intro="transition.fadeIn:ms/options"
.
Works like a charm :)
Interesting. Would love to get my hands on that, please :) Also, as for more use cases: That's my hope (fingers crossed).
There's probably more use cases for velocity+Ractive than transitions only tho.. right? :)
@cfenzo: Probably decorator too, using data state to trigger animations
@julianshapiro I'll clean it up a bit and share after work tomorrow :) @martypdx yeah, that too!
@cfenzo has been patiently waiting on me to take a look at it, but I've been preoccupied with the removal of Velocity's jQuery dependency.
I will finally look at this tomorrow and get back to both of you in this thread. Ty!
@Rich-Harris as @julianshapiro mentions above, we've been waiting for the removal of Velocity.js' jQuery dependency. It's really all about the AMD loading and how it ends up being implemented in Velocity (how to get Velocity in various environments, with or without jQuery). Hopefully it will be ready for primetime in a day or two :)
(But we do use it in production already ;) )
@julianshapiro @Rich-Harris would love a velocity-power transition plugin as well :)
@cfenzo just checkout your ractive-transitions-velocity
, look like it still has jQuery dependency, any plan to migrate?
Is there a
transitions
adaptor out there today to perform transitions as basic CSS animations? It'd be nice to be able to do, say:...which will add the
fadein
class to the element and wait for theanimationend
event. I believe this is easily achievable, but I was wondering if there was already a plugin written for this.