Hi,
Web Animations defines Animatable.getAnimations() (where Animatable is
implemented by Element and a forthcoming PseudoElement interface) and I
think we've agreed to add Document.getAnimations() as well.[1]
I've found two problems with the first method which I'm going to call
Element.getAnimations() for now since PseudoElement doesn't exist yet.
PROBLEM 1. Element.getAnimations() doesn't work on a subtree
Recently I was working on a presentation where I wanted to use script to
restart all the animations in a particular slide, represented by a
<section> element.
What I really wanted to do was something like:
section.getAnimations().forEach(anim => anim.currentTime = 0);
However, Element.getAnimations() doesn't return animations from its
descendants (unlike querySelectorAll, getElementById, etc.).
To further complicate things, Document.getAnimations() *does* return
animations from its desendants (or will, once it is specced).
PROBLEM 2. getAnimations() relies too much on the order in which
animations are returned
Whenever you see code using getAnimations(), it almost always looks like
this:
var anim = elem.getAnimations()[0];
That's really brittle. If some style is added that causes a transition
to fire on elem, you may end up getting the wrong result.
Of course, you can go through all the animations returned from
getAnimations() and test their animationName/transitionProperty
attributes and make sure you get the right object, but most people won't
bother.
PROPOSAL: Add some options to getAnimations()
At a minimum, I think we need:
* transitionProperty - used to filter by 'transitionProperty' which is
only set on CSS transitions
* animationName - used to filter by 'animationName' which is only set on
CSS animations
* id - used to filter by 'id' which may be set on script-generated
animations
* subtree - true means to fetch animations from descendents too (based
on the Mutation Observer API)
It's not obvious to me what the default value of subtree should be. I'd
say 'false' except that would prevent using the same options object on
Document.getAnimations(). Perhaps true? Given that most people will use
this on leaf nodes anyway, maybe that would be ok?
It's also not clear if we should only inspect the transitionProperty on
CSSTransition objects, or if script-generated objects that define their
own transitionProperty should be considered too. I guess they should.
Likewise for animationName and CSS Animations.
Some usage patterns are bogus, e.g. passing subtree:false to
Document.getAnimations() or specifying both transitionProperty and
animationName (except in rare cases where script added these
properties), but maybe that's ok.
Example usage:
// Get the animation I just added
elem.style.animation = 'move 3s';
var anim = elem.getAnimations({ animationName: 'move' })[0];
// Get all transform transitions in this section
section.classList.add('move-in');
var transitions =
section.getAnimations({ transitionProperty: 'transform' });
As you can see in the first example, we still have the '[0]' thing
there. It's more safe now since we're only dealing with CSS Animations
named 'move', but you could still get the wrong result and it's also a
bit of an eyesore and pain to type.
I wonder if it's worth following the querySelector/querySelectorAll
pattern and having a pair of functions: getAnimation/getAnimations?
In the singular, if there were multiple matches on the same element
you'd return the one with the highest composite order[2] since that's
most likely to be the one that you want. If you had multiple matches
within a subtree, I'm not sure: tree order or composite order.
Possible future extensions:
* Parameters to get only CSS transition or only CSS animations?
* Parameters to get all animations that affect certain properties? e.g.
all animations that affect either the 'opacity' property or
'visibility' property.
These can be easily implemented using Array.filter() so there's no
urgency for these.
What do you think?
Brian
[1] https://lists.w3.org/Archives/Public/public-fx/2015JulSep/0073.html
[2] http://w3c.github.io/web-animations/#the-effect-stack