greensock/GSAP

onRepeat not getting getting called when time is close to a multiple of the duration of a tween

mdatsev opened this issue · 3 comments

When the time lands on values that are close (but not exactly equal) to a multiple of the duration of a tween, the onRepeat call will not be called.

Here is an example:

gsap.to({ x: 0 }, {
  x: 100,
  duration: 3,
  repeat: 4,
  onRepeat: () => {
    console.log("Repeat called!");
  },
});

for (const time of [
  0, 1, 2, 3, 4, 5, 6.0000001, 7, 8, 9.0000001, 10, 11, 12.5, 13,
]) {
  gsap.updateRoot(time);
}

In this case we see only 2 console.log's (when the time reaches 3 and 12.5 - which are either equal or after the repeat time), but we expect 4 console.log's (also when the time is close to 6 and 9).

Here is a full reproduction example: https://codepen.io/mdat/pen/wvLOMwV
And here is an example with other slightly changed time values which works as expected (called 4 times): https://codepen.io/mdat/pen/qBzvNGp

This might not seem important for a real-world application, but if the framerate is consistent and we happen to choose a duration which is multiple of it, it is quite possible to sometimes land on a value this close to it and get unexpected behavior. Which happened to our team and it was quite difficult to debug.

Yes, there is rounding that occurs internally in order to protect against a bunch of edge cases (trust me, it's a good thing). So I'd recommend applying similar logic in your code. For example:
https://codepen.io/GreenSock/pen/XWLGprr?editors=0010

Hello, thank you for the quick response and suggestion!

Unfortunately I don't think this method will work in general. We have some durations which are calculated from other parameters and they are not always integers. See here for example:

https://codepen.io/mdat/pen/OJeqWrd?editors=0012

If we set the scale to 1 it works, but if scale up the duration and times by a factor of 1.1, which should in theory keep the same behavior the bug still reproduces. Do you have any suggestions for a general workaround?

Sure, you're just doing the correction at the wrong spot. Here's an even easier solution:
https://codepen.io/GreenSock/pen/vYqPwxO?editors=0012