Having difficulty animating camera rotation in ThreeJS with Tween

I am facing an issue with animating the ThreeJS camera rotation using TweenJS. While I can successfully tween the camera position, the camera.rotation does not seem to update as expected.

To illustrate my problem, I have created a simple example based on the code provided in the official ThreeJS documentation:

The core of the issue is demonstrated by the following:

new TWEEN.Tween(camera.position).to({x: newPos.x, y: newPos.y, z: newPos.z}).start()

works flawlessly, whereas this:

new TWEEN.Tween(camera.rotation).to({x: newRot.x, y: newRot.y, z: newRot.z}).start()

fails to produce any change in the camera rotation.

My understanding is that the code should be fairly easy to interpret:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );

var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );

camera.position.z = 5;

var animate = function () {
  requestAnimationFrame( animate );

  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;

  renderer.render( scene, camera );
  
  TWEEN.update(); // NOTE: I added this too
};

animate();

// NOTE: I added this:
// In a few seconds, tween the camera rotation
setTimeout(() => {
  const newRot = {x: 1, y: 1, z: 1};

  console.log('Changing camera rotation from:');
  console.log(camera.rotation);
  console.log('to:');
  console.log(newRot);

  new TWEEN.Tween(camera.rotation).to({x: newRot.x, y: newRot.y, z: newRot.z}).start().onComplete(() => {
    // Note that it doesn't change at all?
    console.log('Camera rotation changed:');
    console.log(camera.rotation);
    
    // Manually setting the rotation works fine??
    console.log('Manually changing camera rotation:');
    camera.rotation.x = newRot.x;
    camera.rotation.y = newRot.y;
    camera.rotation.z = newRot.z;
  });
  
  // Tweening the position is no problem??
  const newPos = {x: 0, y: 0, z: 2};
  
  new TWEEN.Tween(camera.position).to({x: newPos.x, y: newPos.y, z: newPos.z}).start()
}, 5000);
body { margin: 0; }
canvas { width: 100%; height: 100% }
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/16.3.5/Tween.min.js"></script>
<script src="https://threejs.org/build/three.js"></script>

Answer №1

To solve this issue, I took a different approach by creating a temporary object called oldRot to tween instead of tweening camera.rotation directly. Upon tween completion, the onUpdate function is triggered to set the camera.rotation back to the value stored in oldRot.

Instead of the original code:

const newRot = {x: 1, y: 1, z: 1};

new TWEEN.Tween(camera.rotation).to({x: newRot.x, y: newRot.y, z: newRot.z}).start();

I modified it to:

const newRot = {x: 1, y: 1, z: 1};
const oldRot = {x: camera.rotation.x, y: camera.rotation.y, z: camera.rotation.z};

new TWEEN.Tween(oldRot).to(newRot).start().onUpdate(() => {
    camera.rotation.x = oldRot.x;
    camera.rotation.y = oldRot.y;
    camera.rotation.z = oldRot.z;
});

This new approach successfully resolved the issue. If anyone knows the reasoning behind why this works, I would appreciate some insights.

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

Trouble with HTML Contact Page Email Delivery

Hello there, I recently set up a contact page for my html website but unfortunately, it's not sending the messages to my email as expected! You can see what I mean in this screenshot -> https://i.stack.imgur.com/2xPXw.png I'm a bit puzzled b ...

Using AngularJS to invoke the ng-required directive and trigger a function

Is it possible to make the required value dependent on a function? Something similar to this? I need to achieve this in order to dynamically change the required attribute for form inputs... HTML: Name: <input type="text" ng-model="user.name" ng-r ...

Utilize JavaScript/jQuery to check for upcoming deadlines in a SharePoint 2013 list

I need to check if an item is due based on its date. When a user creates an item with a date in the format MM/DD (e.g., 06/15), I want to determine if that date falls within the next 30 days, turning it red, within the next 60 days, turning it orange, or g ...

Is it an error to pass arguments using square brackets when requiring a node module?

Recently, I came across this piece of nodeJS code on a GitHub repository: var env = process.env.NODE_ENV || 'development' , config = require('./config/config')[env] , auth = require('./config/middlewares/authorization') , mon ...

show an HTML webpage within a <div> container using AJAX technology

I am trying to include an HTML page named Introduction.html (located in the same folder as x.html) within div1. However, it does not seem to be loading properly. Below is a snippet of the code from x.html x.html <!DOCTYPE html> <h ...

Ways to include a variable in a string when using the .open("GET", "[...]") method

Is it possible to include a variable in the URL using JavaScript and PHP interaction? requeteAjax.open("GET", "../src/App/handler.php?id="); For instance, if the event number is 13, the desired URL should be: requeteAjax.open("GET", "../src/App/handler. ...

Incorporate the ability to display a shape on a map when hovering over a table element, without the need to manually code a JavaScript function for every instance

I came across a script online that allows me to hover over text and have a shape appear on an imagemap. It's functional, but only works for a single instance. Is there a way to implement a JavaScript that handles individual instances so I don't h ...

Maximum opacity in Three.js fog

My Current Endeavor: I am in the process of developing a lightweight GIS application with topography. One feature I want to implement is atmosphere haze. The Code I'm Working With: (Please bear with me as I have multiple scenes) fogColor = new T ...

Unveiling an HTML file using the express.static middleware on Replit

When using Replit to render an HTML file with res.sendFile within an app.get function, everything works smoothly. I can include logos, styles, and JavaScript logic files by utilizing the express.static middleware. However, if I attempt to also make the HTM ...

Moodle API feedback

Is there a way to extract specific data from the API response by targeting a particular response field? var domainname = 'https://sandbox.moodledemo.net'; var token = '234bc817adf979e93f442946c00aa223'; var fu ...

What is the best way to implement a slide-down animation on a stateless component in React JS using either ReactCSStransitionGroup or ReactTransition

I am looking to create an animation for a stateless component that starts off with display:none, and then becomes visible when the parent component's state changes. I want it to slide down like a dropdown menu effect. I am new to animations and have b ...

The instance cannot be accessed by ES6 class methods

Having trouble accessing the this instance in one of my methods within a class that I created. In my router, I am calling the method like this: import Emails from '../controllers/emails' import router from 'express' .... route.post(&a ...

What steps are involved in creating a video playlist with YouTube videos?

Is there a way to create a dynamic video playlist that supports embedded YouTube videos without refreshing the page? If a user clicks on another video, I want the video to change dynamically. You can check out this for an example. Do jPlayer, Video.js, Fl ...

Struggling to display Firestore data in a React component - useRef() does not trigger re-render and useState() throws an error

I am currently working on a project involving a React component called Dashboard. The component includes various features such as loading data from a Firestore database and displaying it on the page. While implementing this functionality, I encountered an ...

Display information from an array in checkboxes. If the same data appears in another array, the corresponding checkbox in React will be automatically checked

I currently have two arrays. The first array, let's call it arr1, contains multiple objects such as [{"Name":"Mr.X"},{"Name":"Mr.Y"},{"Name":"Mr.Z"}]. The second array, named arr2, holds a few values like [{"Name":"Mr.Z"}]. My goal is to display all ...

Leveraging angular.forEach for JSON Iteration

In my app and controller, I am working on creating a "flow chart style" question and answer system. To keep track of the current question and answer, I am using variables like $scope.ActiveQuestion and an array named $scope.ActiveAnswers. I am struggling ...

Using react-i18-next with .json or .js files: a simple guide

Although I am familiar with using i18-next in react components, my current challenge is to import data from either a JS file or JSON file for better code separation. The issue is that I am unable to use the useTranslation hook in those files. I am looking ...

Displaying properties of a class in Typescript using a default getter: Simplified guide

Here is an interface and a class that I am working with: export interface ISample { propA: string; propB: string; } export class Sample { private props = {} as ISample; public get propA(): string { return this.props.propA; } public se ...

Can transitions be applied to links in this manner?

Having an issue with ajax requests, I am currently resorting to using JavaScript linking. This is how I normally link: window.location.href = ('file:///android_asset/www/custom/kontakty.html'); I am curious if it's possible to add a transi ...

Ensuring the correctness of a JSP form prior to submitting it

I am experiencing an issue with my form in JSP. The input fields are marked as "required", but when I submit the form, it still allows submission even if the required fields are empty. I am confused by this behavior and would greatly appreciate any help. ...