tweenjs / tween.js

JavaScript/TypeScript animation engine

Home Page:https://tweenjs.github.io/tween.js/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Tween can't be restarted from onComplete callback.

prachtan opened this issue · comments

tween.js v20.0.3
In older versions of tween (for example v16), tween object could be restarted from onComplete callback:

        // Tween state.
        this._jumpTweener.stop();
        this._jumpTweener.to({jumpFactor : 1}, 500)
        .onComplete(() => {
                this._jumpTweener.stop()
                .to({jumpFactor : 0}, 500)
                .onComplete()
                .start();
        })
        .start();

In the new implementation it doesn't works (start() has no effects) because this._isPlaying flag is set to false after calling onComplete callback:

} else {
	if (this._onCompleteCallback) {
		this._onCompleteCallback(this._object)
	}

	for (let i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {
		// Make the chained tweens start exactly at the time they should,
		// even if the `update()` method was called way past the duration of the tween
		this._chainedTweens[i].start(this._startTime + this._duration, false)
	}

	this._isPlaying = false

	return false
}

The workaround for this is add a setTimeout() but is there any reason for that order of setting this._isPlaying flag?
The tween object in onComplete callback shouldn't have a "stopped" state (isPlaying === false)?

Hmmm. Good point. Would welcome a fix for this!

In the meantime, you can use queueMicrotask instead of setTimeout, which is synchronous.

Another alternative is to make two tweens.

Yet one more (in that specific case is to use yoyo):

        // Tween state.
        this._jumpTweener.stop();
        this._jumpTweener.to({jumpFactor : 1}, 500)
        .yoyo() // goes to 1, then back to 0
        .start();

(untested)

Closing as I think the alternatives are ok for now, but would be willing to take a PR for it.