I am currently working on my three.js app setup and I am facing a challenge with creating a smooth transition between two models.
The desired effect is to have the first model quickly scale down to zero, followed by the second model scaling up from zero to its correct size.
My approach involves using tween.js, however, when a user interface event occurs rapidly while the previous animation is still running, the animations overlap and become chaotic.
What I want is to queue up the animations since my tweens have side effects in the 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 issue arises when the transition is triggered by a radio button list, causing complications when switching between models quickly.
This is because multiple sets of tweens can end up playing simultaneously. I have added some console.log()
statements to demonstrate this:
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 am struggling to find a solution that avoids side effects, as the animation must be completed before setting visibility to false, and I am unsure how to append to the existing animation queue.
Is there a method or technique that I am overlooking?