Utilize THREE.js to control the camera with a button click

I'm looking to add separate buttons on my website, where each button triggers the camera to move to a different position within the scene. How can I achieve this? Currently, I have set up a system where pressing a button leads to a sequence of predefined camera positions, but I want each button to move the camera independently to specific spots in the scene.

Below is the code snippet I'm currently working with:

camera.position.set(100, 0, 400);

function render() {
    requestAnimationFrame(render);
    renderer.render(scene, camera);
    TWEEN.update();
}

function moveCam() {
    var pos1 = new TWEEN.Tween(camera.position).to({ y: 300 }, 3000).easing(TWEEN.Easing.Quadratic.InOut);
    var pos2 = new TWEEN.Tween(camera.position).to({ x: -400 }, 4000).easing(TWEEN.Easing.Quadratic.InOut);
    var pos3 = new TWEEN.Tween(camera.position).to({ y: -10 }, 4000).easing(TWEEN.Easing.Quadratic.InOut);
    var rot1 = new TWEEN.Tween(camera.rotation).to({ y: -1 }, 4000).easing(TWEEN.Easing.Quadratic.InOut);
    var pos4 = new TWEEN.Tween(camera.position).to({ x: 600 }, 6000).easing(TWEEN.Easing.Quadratic.InOut);
    var pos5 = new TWEEN.Tween(camera.position).to({ y: -400 }, 2000).easing(TWEEN.Easing.Quadratic.InOut);
    var rot2 = new TWEEN.Tween(camera.rotation).to({ y: -5 }, 2000).easing(TWEEN.Easing.Quadratic.InOut);
    var pos6 = new TWEEN.Tween(camera.position).to({ z: 10 }, 5000).easing(TWEEN.Easing.Quadratic.InOut);
    var rot3 = new TWEEN.Tween(camera.rotation).to({ y: 0 }, 2000).easing(TWEEN.Easing.Quadratic.InOut);

    pos1.start();
    pos1.chain(pos2);
    pos2.chain(pos3, rot1)
    rot1.chain(pos4)
    pos4.chain(pos5, rot2)
    rot2.chain(pos6)
    pos6.chain(rot3)

Answer №1

Perhaps consider the following approach:

Opt for using a single tween instead of individual tweens for each button. This method ensures that there will not be any interference between them:

var positionTween = new TWEEN.Tween(camera.position)
    .easing(TWEEN.Easing.Quadratic.InOut);
var rotationTween = new TWEEN.Tween(camera.rotation)
    .easing(TWEEN.Easing.Quadratic.InOut);

Make sure to define the positions and rotations for each button comprehensively. It is essential to include all three components when defining a position or rotation value. Omitting a value implies no change, with the camera position depending on its previous state:

In this scenario, the buttons' id attribute is utilized to retrieve the position data. The assumption here is that the HTML structure for the buttons resembles:

<button id="button1" class="camera-button">Position 1</button>

The corresponding JavaScript code would be:

var buttonCameraSettings = {
    button1: {
      position: {x: 1, y: 0, z: 0},
      rotation: {x: 0, y: Math.PI, z: 0}
    },
    button2: {
      // ...
    }
};

You can now set up an event listener for all buttons to retrieve the respective settings:

var button1 = document.getElementById('button1');
button1.addEventListener('click', function(ev) {
  var buttonId = ev.target.id;
  var cameraSettings = buttonCameraSettings[buttonId];

  updateCameraTweens(cameraSettings);
});

For the final step, the updateCameraTweens function should look as follows:

function updateCameraTweens(params) {
  if (params.position) {
    positionTween.stop();
    positionTween.to(params.position, 1000).start();
  }

  if (params.rotation) {
    rotationTween.stop();
    rotationTween.to(params.rotation, 1000).start();
  }
}

If varying durations are required for different animations, simply include those values in the parameters.

It's worth noting that for optimal results, especially with rotations, it is advisable to animate the object's quaternion rather than the Euler angles stored in camera.rotation due to mathematical reasons:

var quatTween = new TWEEN.Tween(camera.quaternion);
var toQuaternion = new THREE.Quaternion();
var toEuler = new THREE.Euler();

// within the updateCameraTweens() function
toEuler.set(rotation.x, rotation.y, rotation.z);
toQuaternion.setFromEuler(toEuler);
quatTween.to(toQuaternion, 1000).start();

Answer №2

If your scene is set to render automatically, you can easily adjust the camera using the following code snippet:

HTML:

<button onclick="panCamera()">Pan</button>

JavaScript:

function panCamera()
{
  camera.position += 10;
}

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

Chrome is having trouble loading basic JavaScript

Here's the JavaScript code I have placed inside the head tag of my HTML: <script type="text/javascript"> function over1() { var img1 = document.getElementById("1").src; document.getElementById("big").src = img1; } function out() { ...

Increment the integer value every time the button is pressed in a continuous manner

As a beginner in the world of Android development, I have encountered a little challenge that I hope someone can help me with. I have implemented two buttons - one to decrease and one to increase a value displayed in a TextView between them. The current f ...

What is the best way to substitute </br> and <br/> with in a text?

Is there a way to replace </br> and <br/> with \n functionally? There seems to be varied responses to this query. Errors are often made when writing the break tag. The solutions for both types of breaks mentioned above are detailed below ...

`How can a child component in Next.js send updated data to its parent component?`

Currently diving into Next.js and tinkering with a little project. My setup includes a Canvas component alongside a child component named Preview. Within the Preview component, I'm tweaking data from the parent (Canvas) to yield a fresh outcome. The b ...

Error: Unable to locate module 'react-calendar-heatmap'

After successfully creating a component that functioned flawlessly in my local application, I encountered an error when attempting to integrate it with npm: ./src/App.js Module not found: Can't resolve 'heatmap-calendar-react' in 'C:& ...

Leverage scope Variable in Angular Service URL

Currently, I am aiming to retrieve data from an API by sending specific search parameters through an AngularJS service. Within my ng-model, I have a variable named "search" that I want to utilize as a parameter in the API URL. My initial (unsuccessful) at ...

Create an express server that can stream mp3 files with the functionality to easily skip forward or rewind

My express server is set up to either download or stream an mp3 file, and here is the code: const express = require('express'); const fs = require('fs'); const app = express(); app.use('/mp3', express.static(__dirname + &apo ...

A Guide to Effectively Extracting Data from Second Level JSON Arrays with

Hi, I'm having difficulty fetching the two attributes under CategoryImage in the second level of the JSON array parsing. Can someone help me with this? Thank you. <script> $(document).ready(function() { var cat=""; ...

What is the best way to achieve a full width table in an HTML format on a smartphone browser?

Apologies for my limited English proficiency. I am currently working on creating a horizontal scrollable table in HTML. My goal is to make the width of the table span beyond the browser's viewing area, so that sticky cell functionality can be implem ...

In TypeScript, the choice between using `private readonly` within a class and

I have been contemplating the best method and potential impacts of referencing constants from outside a class within the same file. The issue arose when I was creating a basic class that would throw an error if an invalid parameter was passed: export cla ...

Unable to activate Vue 13 keyCode in a text field using jQuery with Laravel Dusk Testing

I've been grappling with this issue for a few days now. I'm trying to create a Laravel Dusk test that incorporates the Vue.js framework. There's a method that should be triggered when the user hits the ENTER key. I recently discovered that ...

Refresh the Content of a Page Using AJAX by Forcing a Full Reload

I have a webpage that automatically updates a section using jQuery AJAX every 10 seconds. Whenever I modify the CSS or JavaScript of that page, I would like to include a script in the content fetched via AJAX to trigger a full page reload. The page is ac ...

Creating clones of <li> elements using JQuery and appending them to the end of a <ul> list

I have a regular ul li list and I am looking to add an additional li based on the first one in the list. Here is the HTML: <div id="gallery"> <ul> <li>Point Nr 1<p>lol</p></li> <li>Point Nr 2</li> <li> ...

How the Marvel of jQuery Ignites the Power of

I require some assistance with the callbacks. It appears that they are not functioning properly. I am in the process of creating a jQuery-based game. I have designated a <div id='button'></div> for all the buttons that will be used ...

conceal the bootstrap navigation bar while the page is being

Struggling to toggle a Bootstrap navbar on scroll? Need some guidance from the pros out there. I admit, my Bootstrap and jQuery skills are pretty basic. The browser console doesn't throw any errors, and I've experimented with fadeIn, fadeOut, add ...

Having trouble with passing props to data() in Vue.js?

I'm facing an issue where I am unable to pass props to data() in my Vue inline template: <network-index inline-template> ... <network-list :data="networks"></network-list> ... </network-index> Inside the Index.vue file, here ...

An element generated through JavaScript fails to display on the webpage

As I navigate through the code with a foreach() loop, my goal is to generate a new div every time a firebase document containing the user's email is encountered. The script involves a blend of react js and javascript as I am still learning the ropes o ...

Having trouble accessing the scrollHeight property of null when using Selenium WebDriver

I am currently working on a function in my code that is responsible for scrolling the page. This particular function was inspired by code used to scrape Google Jobs, which can be found here. However, I encountered an error that reads "javascript error: Ca ...

Material-UI: The `paperFullWidth` key passed to the classes prop is not supported within the WithStyles(ForwardRef(Dialog)) component

When using Material-UI, please note that the key paperFullWidth provided to the classes prop is not implemented in WithStyles(ForwardRef(Dialog)). You are only able to override one of the following: root. <Dialog classes={{ paperFullWid ...

Steps for setting all textareas on a website to "readonly" mode

My website contains numerous textareas but they currently do not have the read-only attribute. It would be very time-consuming to manually add the readonly attribute to each one. Is there a more efficient method to make all textareas read-only? ...