Thank you. After our discussion on github, I was really inspired.
I now think I should actually leave animated properties around instead of
clearing them. This greatly simplifies how effects are created, and defining an
effect as a reversed version of another becomes very easy.
Putting an absolutely positioned element back to normal flow, for example, can
be achieved by chaining a zero duration, forwards filled, "position: static"
effect.
I wonder if it's a web-animations way of doing things?
Also curious about two things:
1. Is zero duration, forwards filled, single keyframe effect valid and fills
with the keyframe?;
```
new KeyframeEffect(el, {position: "static"}, {fill: "forwards"}) // is el's
position static after the effect is played?
```
2. Are partial keyframes valid and properties specified in a keyframe extends
to the next one?
```
el.style.position = "static";
new KeyframeEffect(el, [{
position: "absolute",
prop: val1
}, {
// is position absolute in this keyframe?
prop: val2
}], {duration: 1000, fill: "forwards"})
```
Thanks.
> On Jun 22, 2015, at 6:21 PM, Shane Stephens <[email protected]> wrote:
>
> On Tue, Jun 16, 2015 at 7:07 PM Glen Huang <[email protected]
> <mailto:[email protected]>> wrote:
> The conversation unfortunately died.
>
> Maybe the use cases aren't compelling enough. That's totally fine. The only
> question I have is that in the responding mail, you said
>
>> You can do this with closures too. Just toggle the class in the classList.
>
> But I don't think I can.
>
> Your original suggestion was that I should negate styles in the keyframes,
> and since the effect is only backwards filled, those negations will go aways
> when the effect is no longer active.
>
> Now, by toggling class I assume you mean I should put these negations inside
> a class and enable that class when closure is called? But now when the effect
> is no longer active, the class won't be removed automatically. So when do I
> remove it manually? There is no hook in the effect to notify me when the
> effect is no longer active.
>
> Basically, you set your final state in CSS then override using the animation.
> For example, before the animation starts you set:
> navBar.style['justify-content'] = "space-between";
>
> Then in your animation, you "animate" justify-content from "center" to
> "center". It holds that value while it fills forwards.
>
> When the animation is done, use the onfinish hook to cancel it, and the value
> stops applying, falling back to the final state you've set up in CSS.
>
> I have another use case that could be covered by this hook: when multiple
> effects are nested, I want some of them to fill forwards, but others to fill
> forwards until the root effect is no longer active. With this hook, I can
> change the nested effect's fill to none in the hook of the root effect.
>
> Again though this is using events to set the visual state, which you really
> shouldn't do. Instead, this sounds like some kind of advanced groups case -
> given that we haven't nailed down basic groups yet I think it's probably a
> way off before we consider looking at it.
>
> You can in general get a mixture of fill effects by refactoring your groups
> appropriately. This doesn't give you everything but it gets you a long way.
>
> Cheers,
> -Shane
>
> So the question is, since such hook doesn't exist, is there any other way to
> achieve the things I described?
>
> In general - yeah, though some of them may be difficult. Another question,
> though, is 'does this hook fit with the realities of animation' - sadly the
> answer here is no, because it's impossible for us to give you an event
> callback in which it's safe to modify visual state.
>
> Cheers,
> -Shane
>
>
> Thank you very much.
>
>> On May 27, 2015, at 3:24 PM, Shane Stephens <[email protected]
>> <mailto:[email protected]>> wrote:
>>
>> Hi Glen,
>>
>>
>>
>> On Wed, May 27, 2015 at 5:09 PM Glen Huang <[email protected]
>> <mailto:[email protected]>> wrote:
>> Hi, I recently tried to manage very complex animation, and realized I need
>> this feature:
>>
>> When animations fire ready and finish events, they first bubble into to the
>> associated effects, if effects have nesting children, recursively bubble
>> into them, after that, bubble back to animations, much like how dom events
>> work.
>>
>> Do you think it makes sense?
>>
>> I think it sounds complicated, and it doesn't match the intention of events
>> well. If you have some specific examples where you want this behavior,
>> perhaps we can work through them with you?
>>
>> My use case is like this:
>>
>> There are many components in a page. Each different combinations of them can
>> chain together to create an animation. To make things manageable, I design
>> the components so that they can each return effects pertaining to its part
>> in different animation sequences. And when a particular animation is
>> required, I select the corresponding components and their corresponding
>> effects, composite these effects and play it.
>>
>> The difficulty is that each components now only has control for its turn in
>> the animation, but sometimes it needs to change styles after/before the
>> whole animation sequence (e.g., pull itself out of flow before/after the
>> animation).
>>
>> You must be walking your component list to generate these animation effects.
>> Why not generate closures for what you need to do before the animation
>> sequence starts while walking the list, then apply them centrally when you
>> start the animation?
>>
>> With the proposed API, it's as simple as changing styles in the
>> corresponding event hooks.
>>
>> Yes, but at the cost of a great deal of complexity in the implementation.
>> You're also assuming synchronous events (more on this below).
>>
>> However, Shane suggested an alternative solution: before the animation
>> starts, change each component's styles to the desired final value, and use
>> backwards filled effect to negate the styles before animating.
>>
>> I think it's a nice solution, but there are a few problems:
>> While returning effects, components' methods need to add/remove styles. You
>> can't embed these actions into the effect itself. This means the effect must
>> be played in the next tick after they are created, which isn't always
>> feasible.
>> Store the effect update in a closure, and run the closure from the same
>> function that plays the animation.
>> This solution requires you to always put the component in the final styles
>> first, but sometimes the component is easier to animate upon the current
>> styles, and only change to the final styles after the animation is finished.
>> Given that additive animation is not yet implemented I can't understand why
>> this would be true.
>> Negating the styles can be difficult, especially vendor prefixes are
>> involved. With event hooks, you can use temporary classes to negate the
>> styles, relying on tools like autoprefixer to deal with vendor prefixes.
>> You can do this with closures too. Just toggle the class in the classList.
>>
>> So, in summary, i think bubbling events to effects should make managing
>> complex animation much easier, and would like to hear your thoughts on this.
>>
>> P.S. In order to make these event hooks practical, I think we should force
>> that the two events should fire in the same event loop as that of the
>> first/last frame. In other words, for example, changing styles in the finish
>> event of a non-forwards filled effect shouldn't cause FOUC.
>>
>> We considered and rejected synchronous events some time back. It's
>> impossible to synchronize with the compositor thread.
>>
>> In general, you should not be making visual changes in event handlers. They
>> can never be genuinely frame-aligned, so doing so is just going to be
>> setting yourself up for FOUC or inconsistent behaviors between browsers.
>>
>> Cheers,
>> -Shane
>>
>> Thank you.
>