Re: [csswg-drafts] [web-animations-1] Make animations become idle when they have an inactive timeline (#2066)

# Proposal for Spec Changes Based on Discussion on 2019-12-18
## Scroll Timeline - Dropping Fill Mode
1. https://drafts.csswg.org/scroll-animations-1/#dom-scrolltimeline-fill - remove fill attribute.
1. https://drafts.csswg.org/scroll-animations-1/#current-time-algorithm - update ScrollTimeline.currentTime calculation as follows:
    - If current scroll offset is less than startScrollOffset, return (0 - epsilon) or -infinity.
    - If current scroll offset is greater than or equal to endScrollOffset, return ( effective time range + epsilon) or +infinity.
    - Consider: do we need explicitly address a case when startScrollOffset equals to endScrollOffset?
1. https://drafts.csswg.org/web-animations-1/#animationtimeline -  add timeline state readonly attribute: TimelineState {Inactive, BeforeStart, InRange, AfterEnd}

Timeline State | Document Timeline | Scroll Timeline | Null Timeline | Animation Behavior
------------ | ------------- | ------------ | ------------- | -------------
Inactive | https://drafts.csswg.org/web-animations-1/#document-timelines: Prior to establishing the time origin for its associated document, a document timeline is inactive. A document timeline that is associated with a Document which is not an active document is also considered to be inactive. | If `scrollSource  `is null, does not currently have a CSS layout box, or if its layout box is not a scroll container, return an unresolved time value. | always | ‘Paused’ animations - no change. Other animations become idle unless animation.currentTime is set.
BeforeStart | never | If current scroll offset is less than `startScrollOffset `| never | Backwards filling animations fill backwards, other show no effect.
InRange | Always when the timeline is active. | If current scroll offset is  greater than or equal to `startScrollOffset` and  less than `endScrollOffset`. | never | Playing normally
AfterEnd | never | If current scroll offset is greater than or equal to `endScrollOffset `| never | Forwards filling animations fill forwards, other show no effect. | Forwards filling animations fill forwards, other show no effect.

## Web Animations Spec Changes
For the purpose of this discussion null timeline is handled the same as inactive timeline.

1.  https://drafts.csswg.org/web-animations/#responding-to-a-newly-inactive-timeline - drop this section. Instead clarify animation state when responding to inactive timeline as follows:
    - Start time is preserved.
    - Hold time is unresolved.
    - Play state is ‘idle’.
1. Add a section “Responding to a newly active timeline”:
    - If hold_time is resolved, calculate start_time based on the hold_time and timeline current time.
1. https://drafts.csswg.org/web-animations/#playing-an-animation-section - update to handle inactive timelines as follows:
    - If the timeline is inactive and both animation start and current time are unresolved, set start time to zero (or timeline.getInitialCurrentTime()) 
1. https://drafts.csswg.org/web-animations/#pausing-an-animation-section - update to handle inactive timelines. Differentiate between states:
    - Start and hold time are unresolved, play state is ‘idle’ (animation.play was not called).
    - Start time is resolved, hold time is unresolved, play state is ‘idle’ (play was called).
    - Start and hold time are resolved, play stay is ‘paused’ (play was called, timeline became inactive, animation.currentTime was set)
1. https://drafts.csswg.org/web-animations/#setting-the-current-time-of-an-animation - drop #3:
    - If animation has no associated timeline or the associated timeline is inactive, make animation’s start time unresolved.
    - This preserves the invariant that when we don’t have an active timeline it is only possible to set either the start time or the animation’s current time.
1. https://drafts.csswg.org/web-animations/#play-states
    1. Include the following condition into the “paused” state definition:
        - If both start and hold time are resolved and timeline is inactive (or null).
    1. Include the following condition into the “idle” state definition:
        - The current time of animation is unresolved, the timeline is inactive and has pending play state.
## Use Cases
1. An animation that is idle until its timeline starts to play
    ```javascript
    scroller.style.overflow="none";
    scroll_timeline = new ScrollTimeline({scrollSource: scroller, ...});
    animation = new Animation(new KeyframeEffect(...}], { duration: 2000}), scroll_timeline);
    animation.play();
    console.log(animation.startTime); // 0
    console.log(animation.currentTime); // null
    console.log(animation.playState); // idle
    ```
1. An animation that is filling backwards until its timeline starts to play.
    - Same as bullet 1.
1. Likewise for the above at the other end of the timeline.
    - _Is it playback rate < 0? If so exactly as bullet 1._
1. Set the initial playback position of an animation so that when its timeline starts to play, it picks up from that point.
    ```javascript
    scroller.style.overflow="none";
    scroll_timeline = new ScrollTimeline({scrollSource: scroller, ...});
    animation = new Animation(new KeyframeEffect(...}], { duration: 2000}), scroll_timeline);
    animation.currentTime = 100;
    animation.play();
    console.log(animation.startTime); // 0
    console.log(animation.currentTime); // 100 
    console.log(animation.playState); // paused
    // make the timeline active
    scroller.style.overflow="scroll";
    console.log(animation.startTime); // 0
    console.log(animation.currentTime); // 100 
    console.log(animation.playState); // running
    ```
1. Hot-swapping timelines (switch from scroll-based to time-based).
    ```javascript
    scroller.style.overflow="scroll";
    scroll_timeline = new ScrollTimeline({scrollSource: scroller, ...});
    animation = new Animation(new KeyframeEffect(...}], { duration: 2000}), scroll_timeline);
    animation.play();
    ...
    scroller.scrollTop = '50px';
    ...
    console.log(animation.startTime); // 0
    console.log(animation.currentTime); // 500 or some other number 
    console.log(animation.playState); // running 

    animation.timeline = document.timeline;
    console.log(animation.startTime); // 0
    console.log(animation.currentTime); // some number based on the new timeline.currentTime
    console.log(animation.playState); // running or finished
    ```
1. Timeline becomes newly inactive while the animation is playing.
    ```javascript
    scroller.style.overflow="scroll";
    scroll_timeline = new ScrollTimeline({scrollSource: scroller, ...});
    animation = new Animation(new KeyframeEffect(...}], { duration: 2000}), scroll_timeline);
    animation.play();
    ...
    scroller.scrollTop = '50px';
    ...
    console.log(animation.startTime); // 0
    console.log(animation.currentTime); // 500 or some other number 
    console.log(animation.playState); // running 
    // Make the timeline inactive
    scroller.style.overflow="none";
    console.log(animation.startTime); // 0
    console.log(animation.currentTime); // null
    console.log(animation.playState); // idle 
    ```
1. Seek an animation that is not attached to an active timeline and get meaningful values out of it.
    ```javascript
    // Continuation of the above
    scroller.style.overflow="none";
    console.log(animation.startTime); // 0
    console.log(animation.currentTime); // null
    console.log(animation.playState); // idle 
    animation.currentTime = 1000;
    console.log(animation.startTime); // 0
    console.log(animation.currentTime); // 1000
    console.log(animation.playState); // paused
    ```
1. Cont. bullet 7 - the timeline becomes active.
    ```javascript
    scroller.style.overflow="scroll";
    console.log(animation.startTime); // some number calculated from the current time of 1000.
    console.log(animation.currentTime); // 1000
    console.log(animation.playState); // running
    ```

-- 
GitHub Notification of comment by ogerchikov
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/2066#issuecomment-568565738 using your GitHub account

Received on Monday, 23 December 2019 19:48:46 UTC