web-animations / web-animations-js

JavaScript implementation of the Web Animations API
http://web-animations.github.io
Apache License 2.0
3.77k stars 408 forks source link

GroupEffect and SequenceEffect: support parent timing, specifically iteration count #152

Open dvoytenko opened 7 years ago

dvoytenko commented 7 years ago

E.g. this should be possible:

new SequenceEffect([
  new KeyframeEffects(target1, keyframes1, {iterations: 2}),
  new KeyframeEffects(target2, keyframes2, {iterations: 2}),
],
{
  iterations: 3
})

Where keyframes1 and keyframes2 would play 6 times each. Per spec:

If an iteration count is specified for the children of a group as well as for the group itself, the effect is as if the iteration count of the group was multiplied with the iteration count of the children.

I'm asking this question now because I'd like to gauge the polyfill feasibility - this appears to be pretty hard to do.

birtles commented 7 years ago

I think you mean 6 times? Yes, that should be possible.

dvoytenko commented 7 years ago

@birtles Yes! Definitely 6 times. I updated the description. How would you approach this? Especially if iterations: 3 becomes iterations: Inifinity? Is it polyfillable in all cases?

birtles commented 7 years ago

@dvoytenko I thought there was a version of the polyfill that did this? I'm not sure what you're trying to do -- polyfill using the native version or KeyframeEffect or write a JS-only implementation -- but in either case I'd just go about it the way the spec describes: calculate the transformed time of the group using the same time calculations used for KeyframeEffects and then feed that in to each child effect as the inherited time.

dvoytenko commented 7 years ago

The current polyfill doesn't implement parent iterations, at least not for when native Element.animate is available. But I also can't see an easy path to polyfilling it in in this scenario.

birtles commented 7 years ago

If you're trying to polyfill using Element.animate I'd just make a separate Animation with a KeyframeEffect and no target element, let the Animation represent the group, read off its progress values from animation.effect.getComputedTiming().progress, convert them to a transformed time, convert that to a local time for each of the child Animations (by working out what their respective start times should be), then use that to set each child's animation.currentTime accordingly.

dvoytenko commented 7 years ago

@birtles I'm pretty sure this would work for most timing properties, except iterations count. You'd basically have to restart said Animation in the end of each iteration and take a risk of desynchronization. Right?

birtles commented 7 years ago

@dvoytenko you don't need to restart the Animation -- just drive its currentTime. If you want to avoid interrupting playback on the compositor then you could just do a comparison between your calculated currentTime and the actual one and avoid setting it if they match.

That said, I believe Shane and Doug found they could collapse most parent timing onto children with the main exception being things like overlapping timing functions.

dvoytenko commented 7 years ago

Cool. In this case this is just a feature request then. Looks like my concern might be unfounded then.