Bug 213163 - [Web Animations] Updating an Animation on an Element fails
Summary: [Web Animations] Updating an Animation on an Element fails
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: Animations (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords: BrowserCompat, InRadar
Depends on:
Blocks:
 
Reported: 2020-06-12 23:17 PDT by travis
Modified: 2021-09-07 06:50 PDT (History)
5 users (show)

See Also:


Attachments
Demo project (3.56 KB, text/html)
2020-06-12 23:19 PDT, travis
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description travis 2020-06-12 23:17:58 PDT
Updating an Animation on an Element in Safari appears to fail when quickly updating animations.

This is critical important in the context of using Web Animations for UI Animation purposes, where a user may click rapidly on an Element. For example, if an animation is being used to back an on/off switch, then the visible state of the animation is critical.

Please watch this video: https://vimeo.com/428712386/f913056c2a

Demo
----
Please see this demo: https://codepen.io/createwithflow/pen/ExPyxex
Or download the same thing here: https://www.dropbox.com/s/gim2pq67ilzlzxo/UpdateAnimationBugSafari.zip?dl=0

This demo uses two animations (mirrored forward and reverse), both affecting the transform property.
When clicking the button the script uses the current time of an animation to determine the new current time for the next animation.
Expected Behaviour
------------------
When quickly clicking the button, the "next" animation should update and be set to a time (t) that mirrors the position of previous animation.
This should cause the element to appear to rotate "backwards" or "forwards" from its current position.

Actual Behaviour
----------------
In both Safari, and Safari Technology Preview 108, the element appears to jump to the wrong state before animating.
In some cases, the animation jumps to the animation's starting position after the animation completes.

Testing
-------
Chrome 83.0.4103.97 - Works as expected
Firefox 77.0.1 - Works as expected
Microsoft Edge 83.0.478.45 - Works as expected

Safari 13.1 – Does not work as Expected
Safari Technology Preview 108 (13.2) – Does not work as Expected

NOTES
-----
Safari and Safari Technology Preview both work when there is a decent amount of time between clicks. Though, it's hard to measure the threshold delta where the bug occurs.
Comment 1 travis 2020-06-12 23:19:09 PDT
Created attachment 401827 [details]
Demo project
Comment 2 Radar WebKit Bug Importer 2020-06-13 08:59:10 PDT
<rdar://problem/64329495>
Comment 3 Antoine Quint 2020-06-13 09:19:00 PDT
I'm getting very different behavior between Firefox Nightly 79.0a1 (2020-06-13), Chrome Canary 85.0.4171.0 and Safari Technology Preview 108 with https://codepen.io/createwithflow/pen/ExPyxex. Firefox and Chrome definitely don't behave like what you have in your screen recording.
Comment 4 Antoine Quint 2020-06-13 09:20:53 PDT
Firefox 77.0.1 and Chrome 83.0.4103.97, the stable releases, behave as shown on the video.
Comment 5 Antoine Quint 2020-06-13 09:21:26 PDT
So, yeah… it seems like everyone has buggy behavior here in non-stable releases.
Comment 6 travis 2020-06-13 09:45:22 PDT
Confirmed, FF Nightly 79.0a1 (2020-06-13) and Chrome Canary 85.0.4171.0 both look like they have issues. 

Firefox Beta 78.0b6 looks good.

I was wondering if there's a better way to set up the animations. For example, waiting for the animation to be ready...

animation.ready.then(function() {
  animation.play
});

-

General question: is there a particular set of browsers I should be testing when submitting tickets?
Comment 7 Antoine Quint 2020-06-13 13:18:19 PDT
Travis, I haven't diagnosed the issue yet to determine what is going wrong, but you can certainly write your content in a much simpler way by using a single animation and calling reverse() on it. Here's an alternative version of your index.js file:


    // Create the animation.
    const animation = document.getElementById('square').animate({
        transform: ['rotate(0deg)','rotate(180deg)'],
        offset: [ 0, 1 ],
        easing: [ 'linear' ],
    }, {
        duration: 1000,
        composite: 'add',
        fill: 'forwards'
    });

    // Let the animation be paused originally.
    animation.pause();

    document.getElementById("button").addEventListener("click", event => {
        // If the animation has not played yet, play it.
        if (animation.playState == "paused")
            animation.play();
        // Otherwise, reverse the playback direction.
        else
            animation.reverse();
    });

As for your question about testing, it's always useful to indicate known behavior difference between Safari/WebKit and other browsers as well as previous versions of Safari in case there is a regression.
Comment 8 Antoine Quint 2020-06-13 13:46:56 PDT
Note also that Safari does not support the "composite" property.
Comment 9 travis 2020-06-13 18:05:28 PDT
Hey Antoine,

I agree that for this particular animation reverse would work. However, we generate some fairly complex sets of animations, and have found that setting our own reversed versions to behave more consistently. Also, without getting into the weeds, we also do some dynamic swapping of whole sets of animations. So the technique is what I was trying isolate.

I should have removed the composite add, I was iterating through some variations on the demo and testing. Forgot to delete that.

I will run some more experiments on my end.

T
Comment 10 Antoine Quint 2020-06-14 01:47:59 PDT
You can also call .cancel() on the animations that are being replaced. I don't know if that will matter in this particular instance, but if you know an animation won't be relevant anymore, this would be a good thing to do. You can also set animation.effect.target = null to no longer apply that animation to its target element.
Comment 11 Antoine Quint 2020-06-16 08:04:09 PDT
The change in behavior between Firefox and Firefox Nightly is due to the use of `composite: add`, which is disabled in Firefox but enabled in Firefox Nightly. Could be the same story with Chrome.
Comment 12 travis 2020-06-16 10:42:39 PDT
Yeah, looks like this was the same issue with Chrome Canary.
I have removed that `composite:add` line from the demo.
Comment 13 Owen Delisle 2020-06-23 10:20:33 PDT
(In reply to Antoine Quint from comment #8)
> Note also that Safari does not support the "composite" property.

(In reply to Antoine Quint from comment #7)
> Travis, I haven't diagnosed the issue yet to determine what is going wrong,
> but you can certainly write your content in a much simpler way by using a
> single animation and calling reverse() on it. Here's an alternative version
> of your index.js file:
> 
> 
>     // Create the animation.
>     const animation = document.getElementById('square').animate({
>         transform: ['rotate(0deg)','rotate(180deg)'],
>         offset: [ 0, 1 ],
>         easing: [ 'linear' ],
>     }, {
>         duration: 1000,
>         composite: 'add',
>         fill: 'forwards'
>     });
> 
>     // Let the animation be paused originally.
>     animation.pause();
> 
>     document.getElementById("button").addEventListener("click", event => {
>         // If the animation has not played yet, play it.
>         if (animation.playState == "paused")
>             animation.play();
>         // Otherwise, reverse the playback direction.
>         else
>             animation.reverse();
>     });
> 
> As for your question about testing, it's always useful to indicate known
> behavior difference between Safari/WebKit and other browsers as well as
> previous versions of Safari in case there is a regression.

The reverse function doesn't actually work in Safari. 

You can see the browser support for the reverse function on MDN here:
https://developer.mozilla.org/en-US/docs/Web/API/Animation/reverse#:~:text=reverse()%20method%20of%20the,animation%20will%20continue%20in%20reverse.
Comment 14 Antoine Quint 2020-06-23 11:21:20 PDT
MDN is incorrect then, reverse() works in Safari as of Safari 13.1.
Comment 15 Owen Delisle 2020-06-30 14:25:25 PDT
Works in 13.1.1 not 13.1. You can get it here https://www.techspot.com/downloads/downloadnow/4185/?evp=e88fa7dde729eadd7478088bf9808c66&file=1

I couldn't find it on the Apple website.
Comment 16 travis 2021-09-02 16:16:01 PDT
Hi, just confirming that this bug still exists.
Comment 17 Antoine Quint 2021-09-07 06:40:56 PDT
We don't support the `composite` property yet, see bug 189299. I expect this is required to get your content to behave as expected.