我有一个Three.js应用程序设置,我试图在两个模型之间添加一个不错的过渡。
它应该迅速缩小到零,然后将下一个模型从零放大到正确的大小。
我正在使用tween.js,如果ui事件再次快速发生而前一个仍在设置动画,那么它们最终将试图一起运行并进行交织。
我只希望它将其添加到队列中,因为补间在oncomplete处理程序中具有副作用。
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();
}
问题在于它附在单选按钮列表上,如果我在两个按钮之间快速切换,则会陷入混乱。
这是因为两组单独的补间可以同时播放。我在其中放置了console.log()
来证明这是正在发生的事情:
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
我想不出没有副作用的写法,因为它需要制作动画,然后将visible设置为false,而且看不到添加到现有队列中的方法。
我想念一个花招吗?
答案 0 :(得分:0)
首先,我使用TweenLite,但我认为您在Tween中具有相同的方法。
我的想法是,您可以算一下单击收音机的次数即可算出必须执行的动画次数。然后,您可以检查第一个动画是否仍在进行中,而第二个动画必须以第一个的“不完整”方法开始。
这是一个例子:
var iterations = 0;
var tweenScaleToZero, tweenScaleUpFromZero;
$('#yourRadioButton').click( function() { iterations++; }
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);
if( ( !tweenScaleToZero.isActive() || tweenScaleToZero === undefined ) &&
( !tweenScaleUpFromZero.isActive() || tweenScaleUpFromZero === undefined) ) {
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);
tweenScaleUpFromZero = new TWEEN.Tween(boxToDisplay.scale)
.to(originalScaleShow, 150)
.easing(TWEEN.Easing.Quadratic.InOut)
.onComplete(() => {
Config.activeBoxName = name;
console.log("oncomplete setActiveBoxTypeByName", rnd);
});
}).start();
if( iterations > 0 ) iterations--;
} else console.log( "Boxes are already animating." );
}