从快速ui事件触发时添加补间以按顺序完成

时间:2018-09-24 13:58:36

标签: javascript three.js tween.js

我有一个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,而且看不到添加到现有队列中的方法。

我想念一个花招吗?

1 个答案:

答案 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." );

}