Re: [web-animations] Simplifying timing groups

Hi Shane,

Thanks for your response. I'll follow up below.

(2013/08/08 13:32), Shane Stephens wrote:
> On Thu, Aug 8, 2013 at 1:25 PM, Brian Birtles <bbirtles@mozilla.com
> <mailto:bbirtles@mozilla.com>> wrote:
>     i. It means you can't convert from an animation's local time to the
>     corresponding document time since timing functions are not always
>     invertible. This introduces all sorts of complexity. For example,
>     for event handling to report both a local time and document time for
>     an event we have introduced uneased timing[1] which is not
>     well-liked and as an alternative we have considered some fairly
>     arbitrary approximations.
>
>
> I think this is a misrepresentation. Every observable animation start,
> end and iteration change has an exact corresponding document time. These
> times are in general derivable from the timing functions.

I think it's reasonably complex.

For example, in Gecko when we evaluate cubic bezier timing functions we 
approximate the curve with straight-line segments to find the t for a 
given x. If we go in reverse where a given y may have multiple t's, we 
can't rely on a table of fixed chord lengths since they may obscure some 
crossings of a given y. I think it could be challenging to define this 
in a way that is consistently implemented and performant if we allow 
arbitrary timing functions. We could probably do something reasonable 
for a restricted set of timing functions though.

Another example of complexity is stepped timing functions where we have 
to be careful how we define which x to return for a given y since a 
single input may map to a whole range of outputs. I think the 'correct' 
answer will depend on a number of factors, possibly the type of event to 
be dispatched or the playback direction.

So I think, while probably solveable, it's complex enough to defer to a 
later stage.

>     It also introduces some as-yet unresolved questions such, "If a
>     timing function on a group causes a child to oscillate between being
>     in and out of the active phase repeatedly, perhaps even a dozen
>     times in 100ms for a spring function, do we dispatch events for
>     every one of those transitions?" (And if we have real spring
>     functions the number of crossings would depend on how you evaluate
>     the function and could be huge.)
>
>
> If we have short iteration durations and lots of iterations we have the
> same problem.

The issue is really the question about whether we should report all 
those starts and ends at all. Sometimes its useful to have them, 
sometimes its not.

I can give a concrete example of this if needed but I think it's simpler 
if we design the model so the question never arises in the first place.


>     iii. It complicates implementation since this feature makes it
>     difficult to decompose timing hierarchies into simple animations
>     that could be passed off to another process or even another API.
>     Without this feature, any timing hierarchy could potentially be
>     flattened down to a series of very simple sub-animations. (For
>     example, an iteration count of a group would be represented by
>     producing several sub-animations, one for each iteration. A
>     direction setting on a group could be represented by flipping the
>     playback rate on some of those sub-animations etc. On the other
>     hand, splitting a timing function on a parent into pieces, then
>     combining the appropriate piece with any timing functions already
>     applied to the child's sub-animations, is far more complex.)
>
>
> This is false. It is entirely possible to decompose timing hierarchies
> with timing functions on groups. Given that timing functions need to be
> represented in the simple sub-animations anyway, it is not much of a
> stretch at all to allow a stacked timing function to be used here.

The claim was it is complex, not impossible.

I still think it's a reasonable bit of work. Even if you don't split the 
timing functions but just inherit the whole list of functions along with 
appropriate offsets you still have to effectively apply playback rate, 
direction changes etc. in *in between* the functions in order to produce 
the same result. You could probably achieve that by modifying the 
offsets into the curves but it's starting to get complicated. (Then if 
you're interfacing onto any system that doesn't support a stack of 
timing functions you have to composite the functions together which is 
probably only possible by approximation.)


>     * GSAP, which has an impressive feature set, has no 'ease' property
>     on TimelineLite / TimelineMax.
>
>
> GSAP allows you to tween both the currentTime and the timeScale on
> TimelineLite and TimelineMax, which is the same thing as a timing function.

timeScale() is just the playback rate. progress(), time() and 
totalTime() likewise correspond to setting the playback position.

You can repeatedly call these methods to emulate a timing function but 
that's the not same as having timing function on a group. You can do 
that in Web Animations too without having timing functions on groups.


>     * WPF which has, by far, the most complicated animation API I have
>     ever seen, only has easing functions on animations.
>
>
> WPF provides at least the ability to accelerate and decelerate
> Timelines, from which both Animations and TimelineGroups inherit.

That's not arbitrary timing functions. That's the same as SMIL3.


>     * SMIL3, as discussed later, which is infamous for its complexity,
>     does not allow arbitrary timing functions on groups.
>
>
> And yet SMIL3 does supply auto-reversing, which is not invertible.

If you model it as additional iterations with direction set, then it's 
invertible in the same way that iterations are invertible--that is, you 
have to know the current iteration but that's generally an easy 
requirement to satisfy.

And SMIL3 still doesn't support arbitrary timing functions on groups.


>     This begs the question, do we really need this?
>
>
> If you choose your features based on what everybody else does, then
> given that 3/4 of the animations engines you supplied provide it, the
> answer is clearly yes. However, I'd prefer to analyse whether this
> feature is *useful* and proceed from there.

None of those APIs allow arbitrary timing functions on groups.


>     * In general, provided the 'current iteration' of each parent is
>     known, it is possible to convert from an animation's local time to
>     document time which may be useful in a number of contexts (it may,
>     for example, be something we expose via the API in future).
>
>
> This is always possible. Note that sometimes multiple document times can
> produce the same local time. Note further that this is already true in
> the presence of iterations, without taking timing functions into account.

That's why I included the condition, "provided the 'current iteration' 
of each parent is known."


>     * There is no need for special overflow fill handling.
>
>
> We already perform special overflow fill handling on Animations. Why are
> TimingGroups different?

It's a different mechanism. The handling for animations doesn't require 
any extra state to be passed around. In fact, if we were to remove 
arbitrary timing functions from groups this behaviour could become a 
property of the animations model.


>     * Media references are not required to support timing functions
>     initially. If timing functions are useful there, we can determine
>     the sort of timing functions that are readily implementable and
>     restrict the set of timing functions permitted accordingly. For
>     example, overshoot doesn't make much sense for media. Likewise, some
>     features of chained timing functions probably don't make much sense
>     for anything other than animations (like the keyframe alignment
>     feature).
>
>
> This is an orthogonal issue to your proposal.

It's not orthogonal because if we have timing functions on groups we 
*must* be able to support easing media since we'll get inherited time 
that is eased, possibly multiple times. It's not clear that that's a 
reasonable requirement for all implementations. I'd be surprised if all 
platforms provide that sort of feature.

By removing timing functions from groups we can restrict the easing 
available on media to that which seems useful and implementable (which 
may be none initially).


> It's probably clear by now that I don't agree with your reasoning. Can
> we come at this question from a use-case based analysis instead?
>
> For a start, timing functions on groups make it easy to:
> (1) keep the timing of a number of animations in sync (by applying the
> function to a ParGroup)
> (2) smear a timing function across a composite effect (for example,
> applying an ease-in across a SeqGroup containing multiple child animations)
> (3) keeping consistent timing across a complex hierarchy of ParGroups
> and SeqGroups
>
> Without timing functions on groups, how would you provide this
> functionality?

There are definitely things that you can't do as easily without 
arbitrary timing functions on groups but I can't find a single animation 
engine anywhere that supports this functionality which suggests that for 
all current concrete use cases authors have managed fine without it.

Rik points out that Flash doesn't support this and yet somehow Flash 
authors have managed pretty well.

Last year in October when we demoed Web Animations we actually used this 
feature to ease both a door and its creaking sound. There are two things 
to note about this use case:

a) It could easily be done by applying the timing function to the two 
child animations independently.
b) It could *also* be done by allowing a restricted set of timing 
functions on groups.

I'm open to the possibility of adding restricted easing behaviour on 
groups like SMIL3 offers. I'd prefer to add that later but would be ok 
with adding it sooner if there is sufficient demand. I think that would 
address a number of the uses you outlined above without introducing many 
of the undesirable qualities of allowing arbitrary timing functions.

I just feel that introducing features that (a) introduce considerable 
complexity, (b) are provided by no other animation platform we've found 
yet, and (c) for which we have yet to find concrete use cases that can't 
be solved by other means, seems like over-engineering for a first 
version of a spec. I think we can add this later if needed.

Best regards,

Brian

Received on Thursday, 8 August 2013 06:30:40 UTC