flickity
flickity copied to clipboard
Flickity animations take forever if your browser is configured to throttle frame rate (and hence requestAnimationFrame callbacks)
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:
- Use Firefox to view that testcase. Click the left/right arrows, and notice how long the animation takes to complete.
- Now, visit
about:configand set preferencelayout.frame_rateto2(to limit the browser repaint cycle to 2-per-second). - 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=0environmental variable in order for thelayout.frame_rateconfig option to have an effect.
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.
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.)
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.
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
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).