Creating a smooth transition curve for moving the camera along the z-axis using JavaScript and Three.js技

I am venturing into the world of Three.js and facing a challenge. In the center of my scene, I have a rotating icosahedron. When I click a button, it should start rotating faster and the camera should move closer to make it appear larger. However, I am struggling with applying an acceleration curve to this animation rather than a linear progression.

I have searched through numerous tutorials and examples, but I have not found a clear explanation of how to achieve a cubic-bezier effect.

I have also attempted to use GSAP for this purpose, but I have not seen any desired effects. If you are unable to assist me directly, perhaps you could recommend some articles or tutorials where I can learn about these types of transitions?

Below is the code I am currently working with:

let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 5000 );
    
let renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

window.addEventListener('resize',() => {
  let width = window.innerWidth;
  let height = window.innerHeight;
  renderer.setSize( width, height );
  camera.aspect = width / height;
  camera.updateProjectionMatrix();
});

camera.position.z = 10;

var pointL1 = new THREE.PointLight( 0xffffff, 2, 30);
pointL1.position.x = -4;
pointL1.position.y = 7;
pointL1.position.z = 8;
scene.add( pointL1 );

var geometry1 = new THREE.IcosahedronGeometry(5, 1);
var material1 = new THREE.MeshBasicMaterial( { color: 0x222222, wireframe: true } );
var icosahedron = new THREE.Mesh( geometry1, material1 );
scene.add( icosahedron );

icosahedron.rotation.y -= 1;

let maxCameraDist = 10;
let minCameraDist = 8;
let cameraDist = 10;
        
let duringChange = false;

function render () {
  if (duringChange == false) {
    icosahedron.rotation.y += 0.001;
    icosahedron.rotation.z += 0.001;
      if (cameraDist < maxCameraDist) {
        cameraDist += 0.05;
        camera.position.z = cameraDist;
      }
    } else {
      icosahedron.rotation.y += 0.003;
      icosahedron.rotation.z += 0.003;
      if (cameraDist > minCameraDist) {
        cameraDist -= 0.05;
        camera.position.z = cameraDist;
      }
  }
}
let loop = function() {
  requestAnimationFrame(loop);
  render();
  renderer.render(scene, camera);
}
loop();
        
document.querySelector('button').addEventListener('click',() => {
  if (duringChange == false) duringChange = true; else duringChange = false;
})
button {
  padding: 20px;
  position: absolute;
  z-index: 2;
}
canvas {
  position: absolute;
  z-index: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
<body>
<button>Change it</button>
</body>

`

Answer №1

Here's an example using the GSAP 3 library which is not deprecated.

You can find the ease options here:

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

let renderer = new THREE.WebGLRenderer({
  alpha: true,
  antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

window.addEventListener('resize', () => {
  let width = window.innerWidth;
  let height = window.innerHeight;
  renderer.setSize(width, height);
  camera.aspect = width / height;
  camera.updateProjectionMatrix();
});

camera.position.z = 15;

var pointL1 = new THREE.PointLight(0xffffff, 2, 30);
pointL1.position.x = -4;
pointL1.position.y = 7;
pointL1.position.z = 8;
scene.add(pointL1);


var geometry1 = new THREE.IcosahedronGeometry(5, 1);
var material1 = new THREE.MeshBasicMaterial({
  color: 0x222222,
  wireframe: true
});
var icosahedron = new THREE.Mesh(geometry1, material1);
scene.add(icosahedron);

icosahedron.rotation.y -= 1;


let cameraDistFrom = 15;
let cameraDistTo = 8;
let rotSpeed = 0.1;
let clock = new THREE.Clock();

function render() {
  let t = clock.getDelta();
  icosahedron.rotation.y += rotSpeed * t;
  icosahedron.rotation.z += rotSpeed * t;
}
let loop = function() {
  requestAnimationFrame(loop);
  render();
  renderer.render(scene, camera);
}
loop();



document.querySelector('button').addEventListener('click', () => {
  rotSpeed = 0.3;
  gsap.fromTo(camera.position, {
    z: cameraDistFrom
  }, {
    z: cameraDistTo,
    duration: 1,
    ease: "back.out(3)"
  });
})
body {
  overflow: hidden;
  margin: 0;
}

button {
  padding: 20px;
  position: absolute;
  z-index: 2;
}

canvas {
  position: absolute;
  z-index: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.4/gsap.min.js"></script>

<body>
  <button>Change it</button>
</body>

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

Challenge with timing in slideUp and slideDown animations (jQuery)

The element with the class "heady" is designed to slide up when the document height percentage is below 25%. If you scroll back up, it should reappear after a delay of 1400ms. The problem arises when this action needs to repeat, as the class does not sli ...

Passing the value in a td element to a JavaScript function using Thymeleaf onClick

Trying to utilize "Thymeleaf" for the first time, I am attempting to pass a value to JavaScript with the following code: onclick="getPropId('${properties.id}')" The corresponding function is as follows: getPropId(inputID){alert(inputId);} Unf ...

Checking for Internet Connectivity in Mobile HTML5

Is it possible to check for internet connectivity on a mobile device? Can websockets be utilized to ping a server and determine if the connection is available? I am feeling frustrated as I believed there was a ping function in websockets for client-side u ...

Tips for modifying hover effects using jQuerystylesheet changes

I attempted running the following code snippet var buttonElement = $('<button>Button</button>'); $('body').append(buttonElement); buttonElement.hover().css('background-color', 'red'); Unfortunately, the ...

Having trouble retrieving the value of the second dropdown in a servlet through request.getParameter

I am facing an issue with storing the value of the second dropdown in a servlet after utilizing an ajax call in Java to populate it based on the selection made in the first dropdown. While I was able to successfully store the value of the first dropdown ...

When a hard refresh is triggered, Vue's navigation guard takes precedence over localStorage

Currently, I am working on implementing a permission check for users before they can access a specific route. I have experimented with using both route.beforeEach and route.beforeResolve. Everything functions as expected if the localStorage within the tab ...

Could not establish a connection with 'http://localhost:3001/user/signup' due to a breach of the Content Security Policy in a web application built with React and Node.js

Currently in the process of developing a signup page with React, utilizing Node JS for the Backend. Encountering an issue when attempting to call the signup api on the Backend as it results in the following error message: "api.js:31 Refused to connect to & ...

Guide to creating varying component sizes using ReactJS and Styled Components

Is it possible to add variation to my button based on the prop 'size' being set to either 'small' or 'medium'? interface Props { size?: 'medium' | 'small'; } How can I adjust the size of the component us ...

On IOS, Three.js ensures that the RGB values of a texture are set to zero whenever the ALPHA value

Working on a WebGL project utilizing javascript and the three.js framework, I am in the process of crafting a custom shader with GLSL. In this shader, I must load various lookup tables to utilize individual RGBA values for calculations rather than renderin ...

Navigate to the specified URL once the Ajax function has completed successfully

I'm having trouble with opening a URL from an Ajax function. It seems like the URL is not being called. This is the code I am using: $(document).on( "click",".btndriver", function() { var id = $(this).attr("id"); var nombre = $(this).att ...

Retrieve the maximum value for each date from MongoDB and store them in an array

Looking for the most effective method to obtain the top "score" for each "date" and save them in an array. Consider more than 50 scores for any given date. The structure of the database is as follows: { "_id" : ObjectId("5c06b91b583248493294"), "c ...

The function for executing the specific command is not recognized and is resulting in a TypeError: client.commands

I'm having an issue with the code below and need a solution. Please help. Error : TypeError: client.commands.get(…).execute is not a function I am encountering difficulty with this specific command in my code: client.command ...

A few of the npm packages that have been installed globally are not functioning properly

After installing npm globally, I checked its version using npm -v and it displayed correctly as 7.13.0. Similarly, I installed heroku-cli globally, but when I ran heroku --version, it returned the error message: C:\Users\MyName\AppData&bso ...

Avoid inputting various symbols into the select2 field

I recently upgraded my select input to use select2: <select id="indivCitizen" multiple="multiple"> <option value=""></option> </select> To fetch data dynamically and enhance user experience: $(doc ...

The sub-menu is being obscured by a PDF element in Internet Explorer, causing visibility issues

I have an object type tag on my page that displays a PDF file. Everything is functioning correctly, but in Internet Explorer, my sub-menu is being hidden behind the object tag. var objTag = $('<object></object>') .attr({ data: source ...

Is there a way to showcase a modal following a timed delay?

I want my modal to appear 2 seconds after the page loads. I've tried setting the state in componentDidUpdate, but I keep getting active: undefined. The active props control the visibility of the modal on the page. When I toggle it to true using the Re ...

Mapping an array of Type T in Typescript using typings

Suppose we have a type T: type T = { type: string, } and we create a function that takes an array of T and returns an object where the keys are the values of each T.type and the values are objects of type T. const toMap = (...args: T[]) => args.red ...

NodeJS - The server returns a 404 error before ultimately displaying the requested page

I'm having trouble with my nodeJS application. When I make an asynchronous call using ajax, the server first responds with a 404 error before loading the page. The application functions properly, but I keep receiving repetitive logs stating "Can' ...

utilizing the entire string rather than just a portion

I was attempting to create a JavaScript jQuery program that vocalizes numbers based on some previously saved data. However, I encountered an issue where only the last number in the sequence was being played (the final character in the string). Below is t ...

NodeJs took an unexpected turn

I’m encountering an issue with an http request to forecast.io. When I make a normal request using $.ajax, everything works fine. However, when I try using the ajax-request module, I receive the following output: SyntaxError: Unexpected token u in JSON at ...