flackr / scroll-timeline

A polyfill of ScrollTimeline.
Apache License 2.0
951 stars 94 forks source link

Disable effect without cancelling animation #179

Closed johannesodland closed 9 months ago

johannesodland commented 10 months ago

If the timeline is inactive, the current implementation disables the effect by cancelling the underlying animation. This can cause issues. If the animation is later cancelled "for real" the animation is already idle and no cancel event will be emitted.

One example of code that is affected is the WPT subtest 'oncancel event is fired when the timeline is inactive.' in cancel-animation.html.

  await waitForNextFrame();
  animation.play();
  await animation.ready;

  // Make the scroll timeline inactive.
  scroller.style.overflow = 'visible';
  scroller.scrollTop;
  await waitForNextFrame();
  // If the polyfill listens for style changes, the timeline should be inactive by this point.
  assert_equals(animation.timeline.currentTime, null,
                'Sanity check the timeline is inactive.');

  const eventWatcher = new EventWatcher(t, animation, 'cancel');
  animation.cancel();
  const cancelEvent = await eventWatcher.wait_for('cancel');
  // Cancel event will not be emitted, and we will never reach code below this point.

This test will time out if the timeline is updated when the source style is changed. The polyfill currently don't detect style changes, and fails at the sanity check, but in the future (PR https://github.com/flackr/scroll-timeline/pull/177) I expect that we will react to style changes.

This PR tries to work around the issue by temporary removing the effect, instead of cancelling the animation, when the timeline is inactive.