Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flickity animations take forever if your browser is configured to throttle frame rate (and hence requestAnimationFrame callbacks) #1305

Open
dholbert opened this issue May 13, 2024 · 5 comments

Comments

@dholbert
Copy link

dholbert commented May 13, 2024

Test case: https://codepen.io/dholbert/pen/XWwbrRK
(This is just the default testcase, which I forked & didn't modify at all)

Steps to Reproduce:

  1. Use Firefox to view that testcase. Click the left/right arrows, and notice how long the animation takes to complete.
  2. Now, visit about:config and set preference layout.frame_rate to 2 (to limit the browser repaint cycle to 2-per-second).
  3. Look at the testcase again and try clicking the arrows.

Actual Results:
The animation still plays every single frame of animation, but in extremely slow motion. So it takes ~20 seconds to complete the animation.

Expected Results:
Animation should still take the same amount of time (1 second or so), and each frame should simply make a huge amount of progress.

Notes:

  • It seems that Flickity isn't tracking how much time passes between requestAnimationFrame calls, to ensure a consistent animation duration and animation speed.
  • This particular configuration option (layout.frame_rate) is something that Firefox users do actually use for accessibility purposes, to reduce motion sickness from smooth animation. (See also Support prefers-reduced-motion media query #951 for a related-but-distinct flickity issue that's affecting this same group of users.)
  • If you happen to test this on Linux with Wayland, note that you may also need to run Firefox with MOZ_ENABLE_WAYLAND=0 environmental variable in order for the layout.frame_rate config option to have an effect.
@dholbert
Copy link
Author

Note that even for users who don't have any particular special configuration, requestAnimationFrame does not guarantee a consistent frame rate, and users presumably will see occasional unexpected hiccups (speedups/slowdowns) with Flickity animations as a result of the fact that Flickity seems to be relying on a fixed frame-rate.

The MDN article on this feature makes several mentions of this:

  • "Warning: Be sure always to use the first argument (or some other method for getting the current time) to calculate how much the animation will progress in a frame"
  • The examples on that article all follow this recommendation to track how much time has actually elapsed.

@dholbert
Copy link
Author

dholbert commented May 13, 2024

Here's a screencast showing this bug in action:
screencast of bug.webm

(The bug is in the latter half of the screencast, after I toggle Firefox's layout.frame_rate pref in about:config.)

@dholbert
Copy link
Author

dholbert commented May 13, 2024

It seems that Flickity isn't tracking how much time passes between requestAnimationFrame calls, to ensure a consistent animation duration and animation speed.

Grounding this in the code a bit: the main animation loop seems to be here:

proto.animate = function() {
  this.applyDragForce();
  this.applySelectedAttraction();


  let previousX = this.x;


  this.integratePhysics();
  this.positionSlider();
  this.settle( previousX );
  // animate next frame
  if ( this.isAnimating ) requestAnimationFrame( () => this.animate() );
};

flickity/js/animate.js

Lines 27 to 38 in a64cc33

proto.animate = function() {
this.applyDragForce();
this.applySelectedAttraction();
let previousX = this.x;
this.integratePhysics();
this.positionSlider();
this.settle( previousX );
// animate next frame
if ( this.isAnimating ) requestAnimationFrame( () => this.animate() );
};

This function and its helpers (e.g. integratePhysics, positionSlider, settle) don't seem to consider the time-elapsed-since-the-last-frame at all. It looks like the position advances by this.velocity, which is a number that decreases/dampens each frame, in a way that's trying to be physics-based but not taking time into account.

@ChasBelov
Copy link

ChasBelov commented May 16, 2024

For me, in Firefox 126, with layout.frame_rate set to 1, I'm seeing full-speed animation when I click the previous chevron. It takes less than a second to go from rectangle 3 to rectangle 2.

Codepen.Screen.Recording.2024-05-16.at.12.44.44.AM.mov

@dholbert
Copy link
Author

For me, in Firefox 126, with layout.frame_rate set to 1, I'm seeing full-speed animation when I click the previous chevron

Closing the loop on this: as discussed in https://bugzilla.mozilla.org/show_bug.cgi?id=1894842#c11 and following comments, it seems @ChasBelov's issue was due to another about:config setting (possibly privacy.resistFingerprinting) which was interfering and causing layout.frame_rate to be ignored.

Given that, let's set @ChasBelov's comment aside & keep this github issue focused on the thing discussed in my initial comment which is the fact that Flickity animations take forever if the actual animation-frame-frame rate is low (via e.g. user preferences like layout.frame_rate in cases where the browser does in fact honor that).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants