Enhance the sequence of tweens by triggering them sequentially in response to rapid UI events

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?

Answer №1

Firstly, I am using TweenLite, but I believe that the same methods can be found in Tween.

In my opinion, you can keep track of the number of times the radio button is clicked to determine how many animations need to be performed. You can then check if the first animation is still ongoing and start the second one in the "oncomplete" method of the first.

Here's an illustration:

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

}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issues with tracking changes in Vue.js when using reactive variables

After triggering a click event, I am attempting to choose a message from a json file. However, I am encountering an issue where the first click does not seem to select anything. Upon the second click, the selected messages are duplicated, and this pattern ...

The context provider in Next.js wraps the App component with a layout component specific to each page, resulting in data

Within my project, I have an authentication context component wrapping the main app component. Simultaneously, I am also attempting to implement a page-specific layout component based on the Next.js documentation found here. I'm unsure if my approach ...

Node.js is throwing GitHub API 401 Bad Credentials error, whereas curl is not encountering the

I am attempting to authenticate on Enterprise GitHub using @octokit/rest. When I execute the following Curl command, I receive a list of API URLs: curl -u "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="80edf9c0e5ede1e9ecaee3e ...

The RSS feed reader is currently malfunctioning

I'm having trouble loading an RSS feed from the following URL: http://solutions.astrology.com/scripts/it.dll?cust_id=aamfha&doc=daily07short/dailyshort.xml Here is the code I am using to try to read it: url = 'http://solutions.astrology.co ...

Angular components are not receiving the Tailwind CSS attributes applied to :root classes

In my Angular 12 project, I have integrated Tailwind CSS. The structure of the package.json is as below: { "name": "some-angular-app", "version": "0.0.0", "scripts": { "ng": "ng&quo ...

What is the most effective method for transferring resolved promise values to a subsequent "then" chain?

Currently, I am grappling with understanding promises by utilizing the Q module in node.js. However, I have encountered a minor setback. Consider this scenario: ModelA.create(/* params */) .then(function(modelA){ return ModelB.create(/* params */); } ...

Use Javascript to display specific div elements by clicking a button

I could really use some assistance, When I attempt to display the select div by clicking the button, the "id" that PHP generates returns a null response in the console. The requirement is to only show the div when clicking on the "Quick Quote" button. Pro ...

"Exploring the Best Locations to Incorporate Plugins in VueJS Webpack

I am trying to incorporate Webpack provided Plugins in order to utilize JQuery globally. Some resources suggest You should add it in the webpack.config.js file under plugins:[] section. However, upon examining my webpack.config.js, I noticed that there ...

Whenever I attempt to populate my modal box with data from my selection, I am greeted with an error message stating "invalid object passed in." What could be causing this issue?

Whenever I click on a customer from my table to display their details in a modal box, I keep getting an error message that says "invalid object passed in." The method client is responsible for populating the data and displaying it through a partial view. T ...

Struggling to incorporate blocks into Jade for Express. Encountering errors like "Max Stack Size Exceeded" and issues with setHeader

I am currently using Express along with a simple express-generator server that I created. My first task was to focus on creating the view layout and extending the index page, but unfortunately, I have encountered some challenges. Throughout my process, I& ...

Can AngularJS support HTML5-mode URL routing in locally stored files (using the file:// protocol)?

Sorry if this question has already been asked, but I haven't been able to find any information on it. I'm working on an AngularJS application that needs to be accessed directly from a hard drive (not through a traditional HTTP server), so the UR ...

The recharts error message displays: "There is no overload that matches this call."

I am currently working on developing a chart in react using the recharts library. To guide me, I am referencing an example provided in their documentation available at this link: https://codesandbox.io/s/zen-ellis-30cdb?file=/src/App.tsx While the project ...

I'm looking for a way to implement a jQuery-style initialization pattern using TypeScript - how can I

My library utilizes a jQuery-like initialization pattern, along with some specific requirements for the types it should accept and return: function JQueryInitializer ( selector /*: string | INSTANCE_OF_JQUERY*/ ) { if ( selector.__jquery ) return select ...

Are there any AJAX tools or packages in Node.js Express for connecting (posting/getting) with other servers and retrieving data?

Can someone please guide me on how to utilize ajax in node.js to send and receive JSON data from another server? Is there a package available that allows for this functionality, similar to jQuery's $.ajax, $.post, or $.get methods? ...

How to include <li> in a preexisting <ul> using JSON data in jQuery

Here is the code snippet I am currently working with: <div id="tags"> <ul> </ul> </div> I want to add some items to the list using JSON data $.getJSON("data.json", function (data) { var html = ''; ...

How can you verify the presence of an object containing specific data within an array using JavaScript?

Currently, I am working with the Vue programming language and have some demo code to showcase: <template> <button @click="checkInList">Check</button> </template> <script> import { ref } from "@vue/reactivity& ...

What is the best way to modify the appearance of the button?

I'm attempting to change the appearance of buttons at the top of a webpage to be square and blue. I have jQuery code for this purpose, but it doesn't seem to be functioning correctly. Here is the snippet of code I am using: $(document).ready(fu ...

Utilizing NLP stemming on web pages using JavaScript and PHP for enhanced browsing experience

I've been exploring how to incorporate and utilize stemming results with JavaScript and PHP pages on web browsers. After running node index.js in the VS Code terminal, I was able to retrieve the output word using the natural library: var natural = re ...

Preparing JSON data for creating a wind map with Leaflet

I am currently working on converting netCDF data to JSON in order to use it with leaflet-velocity. This tool follows the same format as the output of grib2json used by cambecc in earth. An example of sample JSON data can be found at wind-global.json. By u ...

VS code is showing the directory listing instead of serving the HTML file

Recently, I attempted to use nodejs to serve the Disp.html file by following a code snippet from a tutorial I found on YouTube. const http = require("http"); const fs = require("fs"); const fileContent = fs.readFileSync("Disp.html& ...