tween.js icon indicating copy to clipboard operation
tween.js copied to clipboard

repeat() doesn't work with chain()

Open MarioAda opened this issue 4 years ago • 12 comments

repeat() and repeatDelay() simply break the chained tweens when used.

Here's an example:

const tween2= new TWEEN.Tween(...)
    .to({ scale: 3}, 1000)
    .onUpdate(() => {
        ...
    });

const tween1= new TWEEN.Tween(...)
    .to({ value: 50}, 2000)
    .onUpdate(() => {
        ...
    });

tween1.chain(tween2);
// tween1.repeat(Infinity); adding this will break the chain and tween2 will not activate
tween1.start();

MarioAda avatar Dec 30 '20 02:12 MarioAda

Hello! In the latest version of of Tween.js? 18.6.4?

trusktr avatar Dec 31 '20 00:12 trusktr

Also, do you have a code sample?

trusktr avatar Dec 31 '20 00:12 trusktr

@trusktr Hey! Yes I'm using "@tweenjs/tween.js": "^18.6.4" I'm using it with Threejs. Keep in mind that this code works great but the animation only activates once, and if I add the repeat functions only "curveTween" activates.

let drawRange = { value: 0 };
let ringOptions = { scale: 1, opacity: 1 };

const ringTween = new TWEEN.Tween(ringOptions)
    .to({ scale: 3, opacity: 0 }, 1000)
    .easing(TWEEN.Easing.Quadratic.Out)
    .onUpdate(() => {
        combo.ring.material.opacity = ringOptions.opacity;
        combo.ring.scale.set(
            ringOptions.scale,
            ringOptions.scale,
            ringOptions.scale
        );
    });

const curveTween = new TWEEN.Tween(drawRange)
    .to({ value: 51 }, 2000)
    .easing(TWEEN.Easing.Quadratic.Out)
    .onUpdate(() => {
        combo.curve.geometry.setDrawRange(0, drawRange.value);
    });
    //.repeat(Infinity)
    //.repeatDelay(500);

curveTween.chain(ringTween);
curveTween.start();`

MarioAda avatar Dec 31 '20 00:12 MarioAda

Here's a codepen starter to make live examples with:

https://codepen.io/trusktr/pen/OJRQjZw

Mind making it live? That way we can see the whole code, in case there's some issue we can't otherwise see from that snippet.

Sidenote, code blocks can be syntax-highlighted here on GitHub by using the file extension, like so:

```js
if (true) {
  console.log('foo')
}
```

which produces

if (true) {
  console.log('foo')
}

trusktr avatar Dec 31 '20 01:12 trusktr

@trusktr Thanks a lot for the tip! Here you go: https://codepen.io/marioada/pen/XWjZaQK As you can see both tweens work individually and when chained! But if we use repeat the "secondTween" stops functioning.

MarioAda avatar Dec 31 '20 01:12 MarioAda

Good catch! Indeed, we should make this work (and add tests to our rapidly growing set of tests!).

In the meantime, here's an easy workaround:

https://codepen.io/trusktr/pen/fb31c7cafb345657e347af2070f8c98c

Sidenote, looks like we're in need of finally implementing this one too, which you might run into if your values between chained tweens don't line up): https://github.com/tweenjs/tween.js/issues/302. See the workaround there.

trusktr avatar Dec 31 '20 02:12 trusktr

Thanks, I like your workaround! But I wonder how we can implement repeatDelay in a clean way until this is fixed

MarioAda avatar Dec 31 '20 02:12 MarioAda

I guess setTimeout will have to do for now, thanks again @trusktr!

MarioAda avatar Dec 31 '20 02:12 MarioAda

True, setTimeout (and/or .delay() for in between the two tweens) will do the trick until we fix this. Example:

https://codepen.io/trusktr/pen/af084b0ed85bf43ee08d1837091f936d

trusktr avatar Dec 31 '20 03:12 trusktr

Ah, turns out we could do what we wanted to all along!

If repeat() is less than Infinity, f.e. 1, then the second chained tween does run, but the whole thing doesn't repeat:

https://codepen.io/trusktr/pen/ac18682fd45045e7aae367606319041b

And I totally forgot! We can make the chain repeat itself by chaining A to B and B to A (making a necklace :slightly_smiling_face:):

https://codepen.io/trusktr/pen/9b999dc592ab014bd5ea0501a6a5b26a

And finally, here's the same necklace, with pauses in between, no setTimeout needed:

https://codepen.io/trusktr/pen/d0d1d5cb416ce089045c2ddc86552665

So the question is, what does the naming of the APIs make people expect?

Technically everything we wanted to do in this issue we can already do, but the naming didn't make that obvious.

Let's revisit naming for a breaking release.

Another idea is, maybe instead of making Tween be everything (including a timeline and set of key frames conceptually), we can create separate classes for things like Timeline, Keyframe, Tween (does the tween job well and nothing else), Chain (which can be instance of Group perhaps)`, or something along those lines. Need some thought...

trusktr avatar Dec 31 '20 04:12 trusktr

I see what you did there, that is indeed very confusing though since "repeat" is supposed to be a substitute for making necklaces but it stops being so when we chain tweens... Anyway thanks a lot for your help and happy new year, cheers!

MarioAda avatar Jan 01 '21 18:01 MarioAda

Happy new year! :)

trusktr avatar Jan 05 '21 05:01 trusktr

Closing since we can repeat a chain by chaining back to the beginning.

trusktr avatar Apr 23 '23 06:04 trusktr