I have a three.js app setup and I'm trying to add a nice transition between two models.
It should quickly scale down to zero, then scale the next model up from zero to its correct size.
I'm using tween.js and if the ui event happens again quickly while the previous is still animating then they end up trying to run together and interleaving.
I just want it to add it to the queue as my tween has side effects in an oncomplete handler.
setActiveBoxTypeByName(name) {
let rnd = Math.random();
console.log("starting setActiveBoxTypeByName", rnd);
let boxToHide = this.scene.getObjectByName(Config.activeBoxName);
let boxToDisplay = this.scene.getObjectByName(name);
let originalScaleHide = new THREE.Vector3(0, 0, 0).copy(boxToHide.scale);
let originalScaleShow = new THREE.Vector3(0, 0, 0).copy(boxToDisplay.scale);
let tweenScaleToZero = new TWEEN.Tween(boxToHide.scale)
.to({x: 0, y:0, z: 0}, 150)
.easing(TWEEN.Easing.Quadratic.In)
.onComplete(() => {
boxToHide.visible = false;
boxToHide.scale.copy(originalScaleHide);
boxToDisplay.scale.copy(new THREE.Vector3(0,0,0));
boxToDisplay.visible = true;
console.log("oncomplete setActiveBoxTypeByName", rnd);
});
let tweenScaleUpFromZero = new TWEEN.Tween(boxToDisplay.scale)
.to(originalScaleShow, 150)
.easing(TWEEN.Easing.Quadratic.InOut)
.onComplete(() => {
Config.activeBoxName = name;
console.log("oncomplete setActiveBoxTypeByName", rnd);
});
tweenScaleToZero.chain(tweenScaleUpFromZero).start();
}
The problem is that it is attached to a radio button list and if I flip between the two quickly then it gets into a mess.
This is because two separate sets of tweens can end up playing at the same time. I put some console.log()
s in there to prove this is what is happening:
starting setActiveBoxTypeByName 0.8409190378614766
oncomplete setActiveBoxTypeByName 0.8409190378614766
oncomplete setActiveBoxTypeByName 0.8409190378614766
starting setActiveBoxTypeByName 0.5498841071087592
oncomplete setActiveBoxTypeByName 0.5498841071087592
starting setActiveBoxTypeByName 0.16717439330596795 // here
oncomplete setActiveBoxTypeByName 0.5498841071087592 // here
oncomplete setActiveBoxTypeByName 0.16717439330596795
oncomplete setActiveBoxTypeByName 0.16717439330596795
I can't think of a way to write it without the side effects as it needs to do the animation and then set visible to false, and I can't see a way to add to the existing queue.
Is there a trick I am missing?
First of all, I use TweenLite but I think you have the same methods in Tween.
What I think is that you can take count of how many times you click on the radio to take count on how many animations you have to do. Then you can check if the first animation is still in progress and the second one has to start in the first one's "oncomplete" method.
Here's an example: