Re: transitions vs. animations

On Mon, Apr 5, 2010 at 2:38 PM, Chris Marrin <cmarrin@apple.com> wrote:
> On Apr 5, 2010, at 10:39 AM, Tab Atkins Jr. wrote:
>> /* In this example, the transition-property value (and its place in
>> the shorthand) also take a function defining a set of keyframes to
>> execute when a given property transitions. */
>> .slider {
>>  left: 0;
>>  transition: left 1s, play(left, bounce) 1s;
>> }
>
> Why are you specifying a property in the play() function? It's encoded in the @keyframes rule, right? I think it would be a bad idea to try to pick out a single property animation from an @keyframes rule where multiple properties are specified. Also, is your new notation intended to avoid the need for an animation property specification? If so, I think that just makes things more confusing. Rewriting this as:
>
>    transition: left 1s;
>    animation: bounce 1s;
>
> seems much more clear.

Because I want the animation to happen when the value for left
changes.  I am explicitly tying a set of keyframes to a transition, so
I can manipulate additional properties while the left property
transitions.  Setting it up separately, as you did in your rewritten
example, would do something completely different (to be precise, it
would bounce the element for 1s immediately upon the element gaining
the .button class).


>> 2. "infinite" is no longer a possible animation duration.  Instead,
>> all keyframes given for the play-during property are assumed to run
>> infinitely (and play-during doesn't accept an animation-play-count),
>> and all keyframes given for the play-in and play-out properties are
>> assumed to be finite.  Play-during simply doesn't *have* a play-count
>> entry.
>
> So if I want to repeat an animation 3 times (to get people to notice but not be too annoying) I would need to use JS or something? I don't think iteration-count is too complex a concept that it should be eradicated.

Hm?  No, play-in and play-out still have iteration-count.  When you
make the element visible, just set a play-in animation with an
iteration-count of 3 and you're set.


>> 3. Any place that accepts a keyframe must also accept a keyframe
>> followed by the 'reverse' keyword, indicating that the keyframes
>> should be run backwards.
>>
>> 4. The operation of (and likely names of) the individual animation
>> properties will have to be tweaked somewhat.  Rather than a single
>> "animation" shorthand with "animation-*" subproperties, you'll have
>> three shorthands and three separate groups of subproperties
>> (play-in-name, play-during-delay, etc.).
>
> You're suggesting 4 changes, each of which addresses a different issue that has been brought up about animations, to wit:
>
> 1) Combining transitions and animations
>
> I think this is a generally bad idea and only leads (as we've seen in the examples given) to a more confusing design.

I'm not combining animations and transitions in general.  I'm
separating them further!  I am, however, allowing keyframes in
transitions, to address a use-case that we identified and that can't
be done well with the current draft.


> 2) Support for looping animations with lead-in
>
> This is an interesting issue that we should discuss as a separate topic.

What precisely do you mean here?  I apologize, but I'm not quite sure
what you are referring to by "lead-in".


> 3) Getting rid of iteration-count (not an issue I had ever heard before)
>
> As I said, I don't think iteration-count adds much complexity so I don't think it should be removed.

I'm only removing it for play-during.  I think the idea of animations
that play when you change states, and animations that play while
you're *in* a state, are usefully distinct.  The former never needs an
infinite duration, the latter always does.


> 4) Reversing transitions, although you are applying this to keyframe animations, another issue I had never heard before.
>
> There has been discussion about this before. It's a useful issue to discuss, but not easy to resolve.

This is a different issue from reversing a transition that gets
interrupted by a change back to the starting value.  That case is
already covered decently by the spec.  Running a keyframe animation in
reverse is just a convenience feature; it's just annoying to have to
spec a keyframe twice if you know you'll be running it in both
directions.


> Generally, I'd much rather see these discussed as separate issues. Doing it like this makes it hard to avoid confusion. But I've given my opinions anyway :-)

Sure, that's reasonable.  Some of these ideas can indeed be discussed
separately.  I'll pull these apart into separate emails to make things
a bit more clear.


>> What's left to define:
>>
>> 1. How a keyframe set takes default values when played in a
>> transition.  Obviously 100% should default to the end-state.  What
>> about times in the middle?  Basically, I'd like to be able to *either*
>> do a simple transition taking a property (say, left) from value A to
>> value B, or do a complex transition using keyframes to take the
>> property from value A to value B with a complex path in between.  I'm
>> not sure what's ideal here yet.
>
> In discussing transitions with keyframes, my opinion has always been that this is an advanced enough technique that it's reasonable to get JavaScript involved to generate keyframes and kickoff an animation.

Eh, I disagree.  I don't see any reason why bouncing an element up and
down as you slide it from left to right should be too advanced.  This
would be the entire thing, in my proposed syntax:

@keyframes bounce {
  from { top: 0; }
  25% { top: 20px; }
  50% { top: 0; }
  75% { top: -20px; }
  to { top: 0; }
}

.slider {
  left: 0;
  transition: left 1s, play(left, bounce) 1s;
}

.slider:hover {
  left: 400px;
}

Done!  Doing the bounce is indeed more difficult than just
transitioning left by itself, but I don't think it qualifies as a
particularly advanced technique.  It's a lot easier than doing the
same in jQuery right now, frex.


>> 2. How a keyframe-based transition and a standard transition interact
>> on the same element.  We may want to say that they *can't* interact,
>> and that transitioning both "left" and "play(left, bounce)" brings the
>> same conflicts that transitioning "left" twice does, and so we resolve
>> them in the same way (last one specified wins).  This would mean that
>> in my first example I'd have to remove the "left 1s" bit and specify
>> what to do with "left" in the bounce keyframes.  Alternately, since
>> you can statically examine keyframes and see what properties are
>> manipulated by one, perhaps just say that if a keyframe manipulates a
>> property, it overrides any manipulation that would be done by earlier
>> keyframes or transitions.  This is likely better, as it handles being
>> able to hook multiple keyframes to the same property elegantly, and
>> also fits with the idea that a plain transition is an
>> instantaneously-produced trivial keyframe.
>
> The current spec (which I obviously favor :-) already has well-defined rules for how animations override transitions. I think that model is sufficient.

I can't find explicit reference to where this is defined.  Do you mean
the line "During the execution of an animation, the computed value for
a property is controlled by the animation. This overrides the value
specified in the normal styling system. In the case of multiple
animations specifying behavior for the same property, the animation
defined last will override the previously defined animations."?

If so, I agree that that is the behavior we want.

(Side question: does this mean that the later animation overrides the
previous one's value for just the conflicting property?  Or will it
override the entire animation, even if multiple non-conflicting
properties are also manipulated in the earlier animation?)


>> 3. How animations of the various types (in, out, during) interact with
>> eachother.  Does during always beat in?  Out beat during?  What about
>> when you fill any of these?  I think this can be resolved fairly
>> easily, if perhaps arbitrarily.
>>
>
> Again, I think the current model presents a sufficient declarative syntax. More complex animations can (and I think should) be done with JavaScript intervention.

I would hope that our discussion elsethread about how to make a box
both bounce and transition from left to right was sufficient evidence
that the current syntax we have is *not* quite sufficient.

I broke down the use-cases we were attempting to address in an earlier
email.  Are you saying that part of my use-case #1 should not be
addressed through pure CSS, even if such a thing could be done
elegantly and simply?


>> A final use-case that hasn't been addressed is "one-shot" animations,
>> which are useful for javascript.  Say you want to throb a button every
>> time someone clicks on it.  This is an animation not tied to a state
>> or a property value change, but rather to an action or event
>> originating from elsewhere.  These would basically just be triggered
>> by javascript.  My initial thought is to just do them as a normal
>> animation tied to a class, and in js just quickly add and remove the
>> class that triggers it.  This doesn't work, though, as removing an
>> animation (or equivalently, making an element no longer match a
>> selector providing an animation) stops the animation (I think?).  Can
>> I just listen for the animationend event and remove the class then?
>> This doesn't help me if I want to restart a running animation if the
>> user clicks again, though.  Being able to directly trigger an
>> animation through JS would be somewhat useful for this sort of thing.
>> I suppose this can wait a bit, though.
>
> Why all that complexity when iteration-count can handle it without any JS needed? Maybe I missing some other issues with iteration-count that make it insufficient?

Sorry, you must have misread the situation I was describing, or
perhaps I'm substantially off-base in understanding how some of this
fits together.

I want to make a button pulse every time a user clicks on it.  In this
particular case, I can start the animation by hooking it to the
:active pseudoclass.  However, as soon as the user stops clicking,
:active stops applying.  I *think* that this makes the animation stop.
 Is this correct?

If the user clicks on the button multiple times in quick succession,
I'd like to stop the pulse and restart it from the beginning.

In the more general case, I'd like to run an animation on some element
when some event happens.  This may be user interaction with the
element, it may be user interaction with some other element, it may be
caused by something other than the user (perhaps an XHR request
finishing).

Can this be cleanly addressed by the current animation model?  I'm not
certain; if there is sufficient detail in the draft to answer my
questions, I can't find it.  I think this use-case will be relatively
common, though, and so want to ensure that it's as easy as reasonably
possible for authors to use.

~TJ

Received on Monday, 5 April 2010 22:33:05 UTC