Manually adjust rotation in Three.js by clicking

I am looking to initiate an animated rotation of an object by clicking a button. I have a basic understanding that the render function operates as an infinite loop and that adding 0.1 to cylinder.rotation.x continuously rotates the object. My goal is to trigger this rotation with a button click, rather than having it run automatically. Here is an example of what I have attempted so far:

<html>
    <head>
        <title>3D Cube</title>
        <style>

            canvas { width: 100%; 
            height: 100% }
            </style>
    </head>
    <body>
        <script src="three.js"></script>
        <script>

            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 cylindergeometry = new THREE.CylinderGeometry(0.1, 0.1, 2, 50, false);
            var cylindermaterial = new THREE.MeshLambertMaterial({wireframe: true, color: 0x000000});
            var cylinder = new THREE.Mesh(cylindergeometry, cylindermaterial);
            cylinder.position.set(0,0,0);
            scene.add(cylinder);

            camera.position.z = 5;

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

                cylinder.rotation.x = 0.1;

                renderer.render(scene, camera);
            };

            render();
            var btn = document.createElement("BUTTON");
            var t = document.createTextNode("CLICK ME");     
            btn.appendChild(t);    
            document.body.appendChild(btn);


            btn.onclick=function(){
                // start animation
                // change cylinder.rotation.x = 0.1; to cylinder.rotation.x += 0.1;
            };
        </script>

    </body>
</html> 

Answer №1

One solution is to move the render() function inside the onclick event.

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

  cylinder.rotation.x += 0.1;

  renderer.render(scene, camera);
};

btn.onclick = function() {
  render();
};

While this approach may work for your specific issue, it may not be ideal for more complex scenarios. A better alternative could involve separating the rendering and cylinder logic like so:

/* global render function */
var render = function() {
  requestAnimationFrame(render);
  renderer.render(scene, camera);
};
render();

/* cylinder rotation logic */
var rotateCylinder = function() {
  requestAnimationFrame(rotateCylinder);
  cylinder.rotation.x += 0.1;
};

/* initiate the rotation */
btn.onclick = function() {
  rotateCylinder();
};
 

This suggestion is generated spontaneously and may have its own limitations.

Answer №2

Set the value "0.1" as a variable and update this variable within the onclick function. Initially, set the variable to zero. Then, increase it by 0.1 within the button's callback.

...
camera.position.z = 5;

var rotationAmount = 0.0; // Start with no rotation.

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

    // Define 0.1 as a variable and increment rotation by that amount in each frame.
    cylinder.rotation.x += rotationAmount; // It begins without any rotation even though "+=" is used.
    // If you omit "+=", your object will remain still at a 0.1 angle every frame change.

    renderer.render(scene, camera);
};
...

Your onclick callback. The animation initiates upon the first button click.

...
btn.onclick=function(){
    // Begin animation
    // Change cylinder.rotation.x = 0.1; to cylinder.rotation.x += 0.1;

    // Update the variable within the onclick function.
    rotationAmount += 0.1 // Each click on the button accelerates the rotation. Starting from zero, the first click sets it to 0.1.
    // Implement any other logic using this button that you can think of.
    if (rotationAtmount > 0.1) 
        rotationAtmount = 0 // One click starts, another stops.
};
...

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

Steps for integrating external components into Laravel 5.3 with VueJs Routes

I am currently working with Laravel 5.3 and utilizing the built-in VueJs components. At this point, my goal is to implement routes into my project. I have attempted to use the following code, but unfortunately, it is not functioning as expected. const No ...

Building a basic music player with the <audio> element and JavaScript / jQuery

I am new to Javascript and jQuery, and this is my first time posting a question here. I have been trying to create custom functions for the HTML5 audio tag by following tutorials online. Despite my efforts, I cannot seem to get it working. Although I can m ...

Tips for sending web form data straight to Google Sheets without the need for an authentication page

Exploring the Concept I have a unique idea to develop a landing page with a form that captures visitors' email addresses in a Google Sheet. After discovering a helpful post containing a Google App script for this purpose, I followed the guidelines o ...

Create groupings within an array based on the month and year using JavaScript

I am working with an array that looks like this: var v = ["07/27/2015", "07/28/2015", "08/29/2015", "08/29/2015", "07/27/2016"] My goal is to dynamically sort this array into a new empty array nv. Once sorted, nv should look like this: var nv = [["07/27 ...

How about wrapping a large amount of text three times and including a "read more" link?

I am tasked with creating an HTML element that automatically detects when text has wrapped three times, truncates the content, and adds a "more..." link at the end of the third line. Can this be achieved? If yes, what is the process to implement it? ...

Vows: proceed to the subsequent error handling process

Can you explain how to properly call the next error function using promise chaining? I initially believed that placing a return statement within the error function would automatically trigger the next error function. //This code is executed in a contr ...

execute javascript code after loading ajax content

Although this question may have been asked before, I am completely unfamiliar with the subject and unable to apply the existing answers. Despite following tutorials for every script on my page, I have encountered a problem. Specifically, I have a section w ...

Using strings "true/false/null" in React Map render instead of true/false/null values

Imagine working in React, where I am looping through JSON data stored in the state variable this.state.searchData. Some of the data values returned from the API call may include true, false, or null. Here is an example: "active": true, "partition": n ...

Executing XSS Reflected Attack by Loading an External JS Script via POST Parameter

Experimenting with XSS attacks on my vbox machines, just for kicks! I have two .html files - one works and the other doesn't. The file that works contains: <html> <head></head> <body> <form method="post" action=&q ...

The constructor window.CCapture is not valid in Node.js environment

Can anyone help me figure out how to load CCapture in Node.js without using a headless browser for recording canvas stream? Every time I try, I keep running into the error message saying "window.CCapture is not a constructor." If you are familiar with the ...

Spinning text within a circular rotation in CSS

Looking for guidance on how to center the "hallo" text inside a circle? Currently experiencing issues with the circle display in IE8 and Firefox. Any suggestions on how to fix this would be greatly appreciated. And here is the link to my code snippet: CSS ...

How do I utilize the file handler to execute the flush method within the Deno log module using Typescript?

I'm having trouble accessing the fileHandler object from my logger in order to flush the buffer to the file. This is the program I am working with: import * as log from "https://deno.land/<a href="/cdn-cgi/l/email-protection" class="__cf_emai ...

I'm encountering difficulties in utilizing Ajax to upload images

I have been attempting to utilize ajax and bootstrap (modal) to add a new product. However, when I click the save changes button, I encounter an issue where all fields return an error message stating 'Undefined index'. Below is the code snippet ...

Change the blue line to a crisp, clean white

Is it possible to customize the color of the blue line that appears when clicked? class Greetings extends React.Component { render() { return <div>Greetings {this.props.name}</div>; } } ReactDOM.render( <div> <p tabInde ...

Updating a hyperlink with data dynamically upon clicking a different button using jQuery

I need to create a script that will add the id of 'peter' to the hyperlink of anchor 'jack' when 'peter' is clicked. <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery. ...

What are the reasons for transitioning from using <script> includes to npm installs?

I am currently working on a VueJS project where I utilize npm to handle all Vue-related components such as vue-resource, router, and Vuex. However, in my index.html file, I have also included additional scripts like Bootstrap, jQuery, and Tween using scrip ...

Ways to Verify the Existence of a Value in an Array Using JavaScript

In my Laravel blade file, I have an array that I am accessing in JavaScript like this: var data = {!! json_encode($data) !!}; When I check the console, the variable is displayed as seen here: variable data console print Additionally, I'm retrieving ...

Enhancing Next.js Images with Custom CSS Styles

I am working with a Next.js component: import styles from '../styles/Navbar.module.css' import Image from 'next/image' export const Navbar = () => { <div> <Image className={styles["navbar-home-icon"]} ...

The full height of the image cannot be captured by html2canvas

It baffles me that html2canvas is failing to capture the full height of the div. html2canvas($container, { height: $container.height(), onrendered: function(canvas) { var data = canvas.toDataURL('image/png'); ...

The function does not provide an output of an Object

I have two JavaScript classes, Controller.js and Events.js. I am calling a XML Parser from Events.js in Controller.js. The Parser is functioning but not returning anything: SceneEvent.prototype.handleKeyDown = function (keyCode) { switch (keyCode) { ...