Creating a mesmerizing display of moving cubes using three.js

I am attempting to reproduce a specific effect showcased in the following link:

In my current project, I have multiple cubes positioned in 3D space along the x and z axis with loops. However, I am struggling to animate them in a precise order. My idea is to loop through the cubes and scale each one along its Y axis with different timing based on its position.

Furthermore, I believe I should utilize setInterval() to trigger the animation sequence, but I am unsure how to implement it...

Below is the code snippet I am using to loop through the boxes and perform scaling:

var r = -1;
(function f(){
    r = (r + 1) % cubes.length;
    cubes[r].scale.y += cubes[r].vy;
    if (cubes[r].scale.y >= 1.4) {
        cubes[r].vy *= -1;
}
setInterval(f, 200);

However, this code does not achieve the desired wavy, step-by-step scaling effect...

For reference, here is a link to the current version of my project: http://codepen.io/gbnikolov/pen/NPGqqq

Answer №1

The animation demonstrated in the provided link showcases the propagation of a sine wave. To recreate this effect, you should adjust the scale of your cubes based on a sine wave function with time and space variables.

Let's start with the time aspect. It is advisable to approach each step separately to understand their contribution to the final outcome. The requestAnimationFrame callback requires a parameter representing the animation time. You can incorporate this into the cube height scale as follows:

function drawFrame(ts) {
    requestAnimationFrame(drawFrame);
    render.render(scene, camera);
    cubes.forEach(function(c) {
        c.scale.y = Math.sin(ts/500) + 1;
    });
}

By dividing the timestamp ts by 500, you can control the speed of the animation. Since the timestamp is in milliseconds, dividing by 500 ensures a complete cycle every 3.14 (pi) seconds. If you want it to last N seconds, divide by 500π and multiply by N.

To ensure all values are positive, we add 1 to the sine wave (since its normal range is [-1,1], adding 1 expands it to [0,2]).

You can introduce a "wave" by incorporating one of the dimensional components into the sine function. Let's begin with the x-dimension:

c.scale.y = Math.sin(ts/500 + c.position.x/4.95) + 1;

The value 4.95 was determined through trial and error; adjusting this number allows you to control the "resolution" of the wave. Higher values result in smoother waves.

Lastly, you can include the z-dimension:

c.scale.y = Math.sin(ts/500 + c.position.x/4.95 + c.position.z/12) + 1;

Similarly, adjusting the z-divider can help you achieve a visually appealing parameter.

You can view the modified CodePen implementation with this solution here:

http://codepen.io/anon/pen/JoYdGv

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

What is the best way to incorporate an npm module in a django-admin widget without the need to install node?

Background I am working on a Django app and need to create an admin widget. The widget will display text in a unique terminal-style format to show forwarded logs from an analytics process managed by Django (using the django-twined extension). To achieve ...

JavaScript Looping through multiple files for upload will return the last file in the series

I'm currently working on implementing a multiple file upload feature using JavaScript. Within my HTML, I have the following input: <input type="file" (change)="fileChange($event,showFileNames)" multiple /> When the onChange event is triggere ...

What is the technique for causing this element to move in reverse?

How can I utilize JS to halt the interval and direct the alien to move backwards once it reaches 700px? I am aware that CSS can achieve this, but I prefer a strictly JS approach. I am struggling with stopping the interval as it hits the left position of 70 ...

What is the best way to utilize the history prop in conjunction with other props?

I am currently using react-router-dom along with react. My goal is to include additional props along with the history prop import React from 'react'; function MyComponent({ history }) { function redirect() { history.push('/path&ap ...

Once the content of a page is retrieved through an AJAX request, I am able to access and select tag elements, however, I am unable to

After making an AJAX request, I received an HTML page $.ajax({ async: true, method: 'GET', url: linkPage, // cache: true, success: function (data) { console.log(data); } }); The received data is ...

Intentionally introduce discrepancies in the errors during validation of an object using hapi/joi

const validationSchema = Joi.object().keys({ Id: Joi.number().required(), CustomerName: Joi.string() .trim() .required() .when('$isInValidCustomer', { i ...

The step-by-step guide to implementing async/await specifically for a 'for loop'

Is there a way to make 'submitToTheOthers' function run after 'let items = []' has completed, without needing an await within 'submitToTheOthers'? I am considering using await within the for loop in 'submitToTheOthers&apo ...

Changing the background color of a PHP input based on the webpage being viewed - here's how!

I'm in the process of creating a website where each page will have its own unique background color. Additionally, I am using a PHP input for both the header and footer sections, which need to change their background colors based on the specific webpa ...

What is the best method for deleting a portion of a string following the final instance of a particular character?

I have a single string that looks like this: "Opportunity >> Source = Email >> Status = New >> Branch = Mumbai" My goal is to truncate the string from the last occurrence of >>. Essentially, I want the resulting string to be: "Op ...

Error: Although precheck is successful, the Chrome API Runtime has exceeded the QUOTA_BYTES_PER_ITEM quota

I keep receiving a QUOTA_BYTES_PER_ITEM error when attempting to store an object, even though my size precheck shows that it should be under the quota. I must be missing something simple here (is this method correct for checking object size?). I've al ...

Is it possible to execute TypeScript class methods in asynchronous mode without causing the main thread to be blocked?

Creating an app that retrieves attachments from specific messages in my Outlook mail and stores the data in MongoDB. The challenge lies in the time-consuming process of receiving these attachments. To address this, I aim to execute the task in a separate t ...

Using GraphicsMagick in combination with Node.js to upload a fresh image file to AWS S3: A step-by-step guide

I've encountered an issue while trying to upload images to S3 - phone images appear rotated due to EXIF data. To address this problem, I came across a tool called graphicsmagick which claims to remove EXIF data and resize images to 500px wide. However ...

Creating Transparent Rounded Backgrounds in Google Chrome Packaged Apps: Achieving the same look as Google Hangout app

Looking at the screenshot below, it is evident that the Hangout app has a fully transparent design with background shadow effect applied to it. I have tried various methods in vain, such as applying CSS styling to the "html" and "body" tags of the page, a ...

How can you use Knex to order the results for each WHERE clause in a SELECT query?

When querying a database using knex, the desired results should be ordered in a specific manner. The current code provides the required results but lacks the expected order. knex("FRUITTBL") .select("FruitTag", "FruitName", ...

Is there a way to update the color of a button once the correct answer is clicked? I'm specifically looking to implement this feature in PHP using CodeIgniter

Within my interface, I have multiple rows containing unique buttons. Upon clicking a button, the system verifies if it corresponds to the correct answer in that specific row. The functionality of validating the responses is already functional. However, I a ...

The IDE is showing an error, but Jest is able to run it flawlessly

I recently created a Jest unit test for a TypeScript function called checkEmail, which internally uses showAlert. The showAlert function in the utils.ts file looks like this: export const showAlert = (message: string) => { toast(message); }; In my ...

How to dynamically insert a hyperlink inside a <td> element within a table using JavaScript

What is the best way to create a hyperlink in a <td> within a dynamic table? I want the first <td> to be a link that combines a URL with the cell value. This is how the dynamic table is created: for (var i = 0; i < riskData.length; i++) { ...

Alternative solution to fix navigation issue in Flex 4.5 when navigatetoURL is not functioning as intended

Perhaps you are aware of the compatibility issues that Google Chrome and Safari have when using navigatetoURL, as it only works in Internet Explorer. To address this problem, I found a code snippet on a forum which consists of a JavaScript function embedde ...

Vue component doesn't update reactively until the template value changes

I have a child component in my Vue application that utilizes Vuex for managing certain values. Currently, when I trigger an action in the parent component, it should also trigger the child component. This is achieved by passing an active boolean prop to t ...

Expand the <div> by clicking on it, then hover away to return it to its normal size

One interesting feature I have on my website is a <div> that expands when clicked, and returns to normal size with another click. However, I am looking for something a bit different... What I want is for the <div> (with the class name .topHead ...