flickity icon indicating copy to clipboard operation
flickity copied to clipboard

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

Open dholbert opened this issue 1 year ago • 5 comments

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 https://github.com/metafizzy/flickity/issues/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 avatar May 13 '24 19:05 dholbert

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 avatar May 13 '24 19:05 dholbert

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 avatar May 13 '24 19:05 dholbert

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() );
};

https://github.com/metafizzy/flickity/blob/a64cc33052150417bb84c724b937097308519d6e/js/animate.js#L27-L38

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.

dholbert avatar May 13 '24 19:05 dholbert

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.

https://github.com/metafizzy/flickity/assets/59780179/d87f8c7c-5778-498a-8a30-bcbde94f2e22

ChasBelov avatar May 16 '24 07:05 ChasBelov

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).

dholbert avatar May 16 '24 17:05 dholbert