tweenjs / tween.js

JavaScript/TypeScript animation engine
https://tweenjs.github.io/tween.js/
Other
9.81k stars 1.41k forks source link

[bug] yoyo has wrong value #677

Open alphabetabc opened 7 months ago

alphabetabc commented 7 months ago

demo

const rootEl = document.getElementById("root");
Object.assign(rootEl.style, {
    width: "800px",
    height: "600px",
});

rootEl.innerHTML = "loading";

const dataX = [];
const dataY = [];

let i = 0;
createAnimationQueue({
    from: { value: 1 },
    to: { value: 1.5 },
    yoyo: true,
    repeat: 3,
    onUpdate: (o) => {
        dataX.push(i++);
        dataY.push(o.value);
    },
    onComplete: () => {
        const chart = ec.init(rootEl);
        chart.setOption({
            xAxis: {
                type: "category",
                data: dataX,
            },
            yAxis: {
                type: "value",
            },
            series: [
                {
                    data: dataY,
                    type: "line",
                },
            ],
        });
    },
});

result

image

mk965 commented 7 months ago

Hello, can you provide a link to the codepen containing the complete demo?

humodz commented 7 months ago

https://codepen.io/humodz/pen/YzgEpXG

When the red ball reaches the end of the animation, on both directions, it blinks to the opposite side for a split second

humodz commented 7 months ago

As a workaround until it's fixed, we can call TWEEN.update twice, like so:

requestAnimationFrame(function animate(time) {
  requestAnimationFrame(animate);
  TWEEN.update(time);
  TWEEN.update(time);
});

This twill trigger callbacks twice which is a bummer, but at least the weird jump goes away

Another workaround would be to generate an yoyo-ified easing function, like as follows:

function yoyo(f) {
  return t => {
    if (t < 0.5) {
      return f(2 * t);
    } else {
      return 1 - f(2 * (t - 0.5));
    }
  }
}

new TWEEN.Tween({ x: 0 })
  .to({ x: 200 }, 2000 * 2) // duration needs to be doubled 
  .repeat(Infinity)
  //.yoyo(true)
  .easing(yoyo(t => TWEEN.Easing.Cubic.InOut(t)))

The only gotcha is that the duration of the tween needs to be doubled, because now a single iteration does both the forward and backward movement.

trusktr commented 4 months ago

Fixed in

Released in v23.1.2

trusktr commented 1 month ago

Re-opening, as the merge for this broke the yoyo demo, which I've reverted. See

We assumed passing unit tests were enough, but we forgot to test the actual yoyo demo! 🥴

bendytree commented 1 week ago

Fwiw - I'm having the same issue on both 23.1.3 and 25.0.0. @humodz's easing workaround worked for me.