ionic-framework icon indicating copy to clipboard operation
ionic-framework copied to clipboard

bug: overlay animations jump forward near end in ios only

Open liamdebeasi opened this issue 3 years ago • 2 comments

Prerequisites

Ionic Framework Version

  • [ ] v4.x
  • [ ] v5.x
  • [X] v6.x
  • [ ] Nightly

Current Behavior

Certain animations appear to "jump forward" when completing on iOS.

This may be easier to try on an actual device, but here is a video below to illustrate:

native ionic

Expected Behavior

I expect the animations to be smooth through the end of the animation.

Steps to Reproduce

  1. Open http://localhost:3333/src/components/action-sheet/test/basic?ionic:mode=ios in Safari (macOS or iOS).
  2. Click "Basic". Observe that the action sheet container translates in but appears to "jump forward" in the last few frames.

Code Reproduction URL

No response

Ionic Info

N/A

Additional Information

No response

liamdebeasi avatar May 27 '22 16:05 liamdebeasi

This is due to a bug in WebKit, the engine that powers Safari and WKWebView: https://bugs.webkit.org/show_bug.cgi?id=241020

In the case of a Web Animation with 2 keyframes, applying the easing to the effect should produce the same visual result as applying the easing to the 0th keyframe. However, on WebKit applying the easing to the effect causes the animation to jump forward near the end.

This does not happen in Chrome or Firefox.


As a workaround, we can apply the easing to the 0th keyframe instead.

liamdebeasi avatar May 27 '22 16:05 liamdebeasi

Effect easing and keyframe easing typically produce different results. Effect easing applies the easing to entire effect (over the total of n keyframes). Keyframe easing applies the easing from keyframe n to keyframe n+1.

However, in the case where there are only 2 keyframes total, the following:

square.animate([
  { offset: 0, transform: 'translateY(100vh)' },
  { offset: 1, transform: 'translateY(0vh)' }
], {
  duration: 1000, 
  easing: 'cubic-bezier(0.32,0.72,0,1)' 
});

should produce the same visual result as:

square.animate([
  { offset: 0, transform: 'translateY(100vh)', easing: 'cubic-bezier(0.32,0.72,0,1)' },
  { offset: 1, transform: 'translateY(0vh)' }
], {
  duration: 1000, 
});

liamdebeasi avatar May 27 '22 16:05 liamdebeasi