JavaScript - Dynamic rotation algorithm

I recently developed a piece of code to manage object rotation in a THREE.js environment. Although the issue is not specific to 3D.

My goal is to have my object (referred to as 'this') rotate by 0.25 radians each time a function is called, until its rotation ('this.clientRotation') matches the target rotation defined in 'this.targetRotation'. The following code snippet represents the contents of an update() function that is continuously invoked during the rendering loop.

In order to prevent oscillation when nearing the target rotation, I had to confirm whether the absolute difference between the current and target rotations was greater than the rotation amount for each call (0.25).

I also needed to check if the rotation difference in radians exceeded 180 degrees, in which case the most efficient turn would be in the opposite direction.

An additional check was required to ensure that the updated rotation remained within -PI and +PI (0-360 degrees).

// Move only if there is a significant difference between target and current rotations
// Rotations range from -PI to +PI
this.rotationSpeed = 0.25;

var absDiff = Math.abs(this.clientRotation - this.targetRotation);
if(absDiff > this.rotationSpeed){

  if(absDiff < Math.PI){

    // Less than 180 degrees, turn towards the target
    if(this.targetRotation > this.clientRotation) this.clientRotation += this.rotationSpeed;
    if(this.targetRotation < this.clientRotation) this.clientRotation -= this.rotationSpeed;
  } else {

    // More than 180 degrees, it's shorter to turn the other way
    if(this.targetRotation > this.clientRotation) this.clientRotation -= this.rotationSpeed;
    if(this.targetRotation < this.clientRotation) this.clientRotation += this.rotationSpeed;
  }

  // Reset rotation to stay within 0-360 degree range
  if(this.clientRotation > Math.PI) this.clientRotation -= Math.PI*2;
  if(this.clientRotation < -Math.PI) this.clientRotation += Math.PI*2;
}

The code functions as intended, but it may be overly complex. Are there more optimized approaches to achieving this standard rotation behavior?

Answer №1

By utilizing ternaries to condense the logic, the following code achieves the same functionality as before. In my opinion, this version is much easier to read, although preference plays a significant role.

this.rotationSpeed = 0.25;
var absDiff = Math.abs(this.clientRotation - this.targetRotation);
if(absDiff > this.rotationSpeed) {
  var lessThan180 = absDiff < Math.PI;
  if(this.targetRotation > this.clientRotation) {
    this.clientRotation = (lessThan180) ? this.clientRotation + this.rotationSpeed : this.clientRotation - this.rotationSpeed;
  } else if (this.targetRotation < this.clientRotation) {
    this.clientRotation = (lessThan180) ? this.clientRotation - this.RotationSpeed : this.clientRotation + this.rotationSpeed;
  }
  this.clientRotation = (this.clientRotation > Math.PI) ? this.clientRotation - Math.PI*2 : this.clientRotation + Math.PI*2; 
}

Your original code may appear complex, but you have done an excellent job at documenting your code through comments and ensuring clarity in readability. One minor suggestion I would make is to use 'if'/'else-if' instead of consecutive 'if' statements, even if you are not a fan of ternaries. This change can enhance efficiency as the 'else-if' conditionals will only be checked if the preceding 'if' statement fails.

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 steps do I need to take to translate jQuery code into standard JavaScript code?

Can someone please help me convert this jQuery code to plain JavaScript? window.addEventListener('scroll', function() { document.querySelectorAll('.container p').forEach(function(el) { var scrollTop = window.scrollY, ...

Feeling puzzled about the next() function in Node.js?

https://github.com/hwz/chirp/blob/master/module-5/completed/routes/api.js function isAuthenticated (req, res, next) { // If the user is authenticated in the session, call the next() to proceed to the next request handler // Passport adds this met ...

Is there a way to undo the click event in Javascript?

Is there a way to revert back to the initial position after clicking? I successfully changed the x icon to a + icon on click, but now I'm struggling to reverse that action. I've tried using MOUSEUP and DBLCLICK events, but they aren't ideal ...

What is the best way to achieve dolly or zoom effects with React three fiber or threejs?

I'm currently working on a react-three-fiber application where I have implemented OrbitControls for my camera controls. My goal is to add on-screen buttons that allow users to manually zoom in or out, similar to how the middle mouse button functions ...

Error SCRIPT1002 was encountered in the vendor.js file while using Angular 8 on Internet Explorer 11

Having trouble getting Angular to function properly in IE 11. I've tried all the solutions I could find online. The errors I'm encountering are as follows: SCRIPT1002: Syntax error File: vendor.js, Line: 110874, Column: 40 At line 110874 args[ ...

Image encoded in base64 not appearing on the screen

Hey there, I'm currently working on implementing a jQuery image uploader that generates a base64 code when an image is selected. function readImage(input) { if (input.files && input.files[0]) { var FR= new FileReader(); FR.onload ...

A guide on retrieving information from a database with PHP and transferring it to Javascript

As I work on creating a website using HTML, CSS, MySQL, and JavaScript, my goal is to allow users to log in and engage in a quiz with 40 questions. Below is the JavaScript code for a countdown timer that includes the "questions" variable. After 40 seconds ...

Find all objects in an array that have a date property greater than today's date and return them

I have an array of objects with a property called createdDate stored as a string. I need to filter out all objects where the createdDate is greater than or equal to today's date. How can this be achieved in typescript/javascript? notMyScrims: Sc ...

eslint is designed to not handle multiple package.json files

There are two package.json files in my project root folder └ app ---- /public └ /styles └ /src └ package.json └ eslintrc.json └ webpack.config.js └ server - /something └ /something ...

Assigning a one-of-a-kind identifier to a cell within a table that was dynamically created using JavaScript and

When using JavaScript to create table cells and rows and populate them with information from a JSON file, I encounter an issue where the unique ids assigned to the table cells in my code are undefined. This causes problems when trying to reference these id ...

Parent-Child Communication in VueJS 2.0: How to effectively pass data from the parent component

Does anyone know a straightforward solution to this issue? I've been struggling to find one. Within my HTML file, there's a button that looks like this: <button @click="showModal">Show Modal</button> By clicking on the button, it t ...

JQuery click event does not play nicely with Javascript array splice functionality

When using for loops, I noticed that array.splice doesn't seem to be working as expected. The array remains unchanged. I tried moving things around and found that it still doesn't work in Chrome. var menu =['#men','#wmen',&a ...

The Google Docs viewer is displaying an empty screen

I have been utilizing the Google Docs viewer on my website: <div class="embed-r embed-responsive-a"> <iframe class="embed-responsive-it" src="https://docs.google.com/viewer?embedded=true&amp;url=http://LINK.PDF"></iframe> </div& ...

Utilizing JavaScript Callbacks in HTML Image Tags

Currently I am working on a small application and looking to include a YouTube section. I have come across a method for obtaining the user's YouTube icon: This is included in the head section of my code: <script type="text/javascript" src="http:/ ...

Using jQuery's $.Deferred in conjunction with the window object's top.postMessage()

I am having trouble understanding how to effectively use $.Deferred. I currently have a situation similar to window.top.postMessage(mystring, myorigin); This works without any issues. I don't need assistance with sending/receiving postMessage What ...

Guide to activating a CSS attribute for the AJAX tab panel with the use of JavaScript

Currently, I am utilizing the ASP.NET AJAX Tab Container with two tab panels. Each tab panel contains a div tag, and by default, my ActiveTabIndex is set to "0." Now, I am trying to apply CSS properties to the div tags using JavaScript without causing any ...

Incorporate interactive click buttons into your Telegram bot

Currently working on a telegram bot using node.js with the telegram-bot API by yagop. https://github.com/yagop/node-telegram-bot-api My goal is to allow users to stop typing messages and instead just click on buttons that will trigger actions. When a user ...

Angular 8 fails to retain data upon page refresh

I have a property called "isAdmin" which is a boolean. It determines whether the user is logged in as an admin or a regular user. I'm using .net core 2.2 for the backend and Postgre for the database. Everything works fine, but when I refresh the page, ...

Having difficulty sending a message from an AngularJS application to an Angular 10 application through an iframe

I have two applications running locally - one is an AngularJS application and the other is an Angular 10 application. I am trying to access a page from the Angular 10 application using an iframe and send a message to it from the AngularJS application. How ...

Verify the functionality of JavaScript to ensure it is enabled and functioning properly

I have experimented with various methods to determine if JavaScript is enabled and running correctly. Typically, I would use a simple test like this: $('.jstest').html('JavaScript works.'); <p class='jstest'></p> ...