Adjusting the color of a box in Threejs through dat.gui.min.js controls

I want to enhance the user experience by allowing them to choose a color from the HEX menu and update the color of the box in the scene using UI controls.

Below is the JavaScript code I have implemented for this purpose:

// author: Arielle Mueller
// date: January 27th, 2021
// filename: 02-Arielle.js

//declare global variables
let scene, camera, renderer;
let box, sphere, orbitControl, control;

function init() {
    scene = new THREE.Scene();
    renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setClearColor( 0xe4cb98 );
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );
}

function createCameraAndLights() {
    camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.x = -30;
    camera.position.y = 40;
    camera.position.z = 30;

    camera.lookAt(scene.position);
    scene.add(camera);

    orbitControl = new THREE.OrbitControls(camera, renderer.domElement);
    //add some ambient light
    scene.add( new THREE.AmbientLight( 0x333333));

    let spotlight = new THREE.SpotLight(0xffffff);
    spotlight.position.set(-10, 20, -5);
    scene.add(spotlight);
}

function createGeometry() {
    let axes = new THREE.AxesHelper(20);
    scene.add(axes);

    // create the ground plane
    let planeGeometry = new THREE.PlaneBufferGeometry(60, 20);
    let planeMaterial = new THREE.MeshLambertMaterial({ color: 0x55cc55 });
    plane = new THREE.Mesh(planeGeometry, planeMaterial);
    plane.rotation.x = -0.5 * Math.PI;
    scene.add(plane);

    //create a cube
    let geo = new THREE.BoxBufferGeometry(5, 5, 5);
    let mat = new THREE.MeshLambertMaterial({ color: 0xcc5577});
    box = new THREE.Mesh(geo, mat);
    box.position.set(20, 4, 2);
    scene.add(box);

}

function setupDatGui(){
    //creating the object that will encapsulate 
    //of the variable that we are interested in

    let gui = new dat.GUI();
    control = new function(){
        this.name = "Controls";
        this.height = 0;
        this.speed = 0.01;
        this.color = '#cc5577';
    };

    gui.add(control, 'name');
    //create a sub-folder
    let sub = gui.addFolder('Sub Folder');
    sub.add(control, 'height').min(-8).max(10).step(0.25).name('Height of cube');
    sub.add(control, 'speed').min(0).max(0.2).step(0.01);
    sub.addColor(control, 'color').onFinishChange(function() { box.color.set = control.color});
    
}

function render() {
    requestAnimationFrame(render);
    orbitControl.update();
    box.color = control.color;
    box.position.y = control.height;
    box.rotation.x += control.speed;
    box.rotation.y += control.speed;
    //scene.rotation.x += control.speed;
    renderer.render(scene, camera);
}

window.onload = () => {
    init();
    createCameraAndLights();
    createGeometry();
    setupDatGui();
    render();
} 

I need some guidance specifically on the render() and setupDatGui() sections:

The controls for adjusting the speed and height attributes are functioning properly. However, I am unsure about how to effectively access and update the color attribute.

    //creating the object that will encapsulate 
    //of the variable that we are interested in

    let gui = new dat.GUI();
    control = new function(){
        this.name = "Controls";
        this.height = 0;
        this.speed = 0.01;
        this.color = '#cc5577';
    };

    gui.add(control, 'name');
    //create a sub-folder
    let sub = gui.addFolder('Sub Folder');
    sub.add(control, 'height').min(-8).max(10).step(0.25).name('Height of cube');
    sub.add(control, 'speed').min(0).max(0.2).step(0.01);
    sub.addColor(control, 'color').onFinishChange(function() { box.color.set = control.color});
    
}

function render() {
    requestAnimationFrame(render);
    orbitControl.update();
    box.color = control.color;
    box.position.y = control.height;
    box.rotation.x += control.speed;
    box.rotation.y += control.speed;
    //scene.rotation.x += control.speed;
    renderer.render(scene, camera);
}

I have attempted to modify the material color instead of directly accessing the .color attribute of the box. However, I am facing challenges in implementing this functionality. The line box.position.y = control.height; works as expected in changing the height of the box.

I am seeking advice on how to proceed with updating the color attribute effectively.

Answer №1

The issue was successfully fixed by utilizing a variable and then integrating box.colorChange into the render function.

//defining the object to contain the desired variable

let controlPanel = new dat.GUI();
control = new function(){
    this.label = "Settings";
    this.height = 0;
    this.speed = 0.01;
    this.color = '#cc5577';
};

controlPanel.add(control, 'label');
//creating a sub-menu
let subMenu = controlPanel.addFolder('Sub Menu');
subMenu.add(control, 'height').min(-8).max(10).step(0.25).name('Height of object');
subMenu.add(control, 'speed').min(0).max(0.2).step(0.01);
var colorChange = subMenu.addColor(control, 'color').onFinishChange((col) => { alert(`The new color is ${col}`);});
colorChange.onChange(function(colorValue){
    colorValue = colorValue.replace('#', '0x');
    box.material.color.setHex(colorValue);
});

}

function animate() {
    requestAnimationFrame(animate);
    orbitControl.update();
    box.colorChange = control.color;
    box.position.y = control.height;
    box.rotation.x += control.speed;
    box.rotation.y += control.speed;
    renderer.render(scene, camera);
} 

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

Inject a dynamic URL parameter into an iframe without the need for server-side scripting

I'm really stuck and could use some assistance with the following issue, as I am unable to solve it on my own :( When a user is redirected to a form (provided via an iframe), there is a dynamic URL involved: website.com/form?id=123 The code resp ...

Implementing multiple condition-based filtering in React Native for arrays

I am looking to apply multiple filters to an array based on certain conditions defined by toggling switches. The issue arises when toggling two or more switches simultaneously, resulting in an empty array. My goal is to retrieve an array containing the tru ...

Clear out all current cookies

I utilized the following JavaScript code to generate a pop-up window on the website that would only appear once. However, my client now wants to launch a new promotion and I am attempting to remove existing cookies so that the pop-up window displays again ...

Javascript for Cordova utilizing WebSocket and incorporating client side certificates

I am looking to establish a secure SSL/TLS connection between my client and server, with only a specific authorized client allowed to connect. To achieve this, I have generated a client certificate using OpenSSL on the server for mutual authorization. The ...

"Enhance your website with a dynamic Jssor slider featuring nested slides and vertical

Exploring the idea of merging the nested slider feature with a vertical thumbnail display. Reviewing the source code for examples image-gallery-with-vertical-thumbnail.source.html and nested-slider.source.html, I am wondering how to effectively combine t ...

How can I reduce the burden of dependencies on users with a pre-built NPM package?

I recently took over maintenance of an NPM package. It has a unique setup where the main file is located in the 'dist/' directory and it's built using webpack (via 'npm run build'). While this works for us, installing this package ...

Vue Websockets twofold

I am experiencing some issues with Laravel/Echo websockets and Vue.js integration. I have set up everything as required, and it works, but not quite as expected. The problem arises when I refresh the page and send a request - it displays fine. However, if ...

I am attempting to activate the "about us" button on the website. I have successfully included the path and added a router link to the containing div of the button. However, there seems to be something

In my app, the first step involves specifying the path in the routing module. Following that is defining the home component, then the app component, and finally creating the button using HTML. Setting up the path in the app.routing.module.ts file <div ...

Flot Graphs: A unique dual-axis line chart with the ability to stack data on one axis

Is it possible to utilize the FLOT Javascript library for creating a chart with dual axis and three data sets? I am specifically looking to have one data set on the left axis and two on the right axis. Ideally, I want to stack the two datasets on the right ...

The function cannot be invoked. The 'Boolean' type does not have any call signatures. An error has occurred in the computed property of Vue3

Currently, I am working on creating a computed property that checks if an item is in the array. The function I have created returns a boolean value and takes one parameter, which is the item to be checked. isSelected: function (item: MediaGalleryItemTypes) ...

Automated algorithm inspecting a variety of hyperlinks

Recently, I've developed an innovative anti-invite feature for my bot. However, there seems to be a minor glitch where the bot fails to remove any links sent within the enabled guild when the command is triggered. This issue specifically occurs in ver ...

Using the onreadystatechange method is the preferred way to activate a XMLHttpRequest, as I am unable to trigger it using other methods

I have a table in my HTML that contains names, and I want to implement a feature where clicking on a name will trigger an 'Alert' popup with additional details about the person. To achieve this, I am planning to use XMLHttpRequest to send the nam ...

NodeJS's pending ajax post using SailsJS

I'm experiencing an issue with processing AJAX data in my sailsJS app. The ajax post data always stays in the pending state, here is the code from my view: <script type="text/javascript"> $('#submit').click(function(){ $.ajax ...

The ref.on() method fails to trigger a response from a function, despite producing the intended outcome

I've been working on developing an app called workspace. I previously asked a question, but I've made more additions to the features now. One of the new features is a remarks system. After experimenting with different versions of my code, the ver ...

There was an error during product validation that occurred in the userId field. In the Node.js application, it is required to

I am in the process of developing a small shop application using node.js, express, and mongoose. However, I have encountered an issue when attempting to send data to the MongoDB database via mongoose. Here is the product class I have created: const mongoo ...

Using the useState hook will help avoid any crashes when running on IE11

I recently added a new repository to my GitHub account. The file dist/index.htm is causing Internet Explorer 11 to crash, displaying the error message: "unable to get property 'root' of undefined or null reference." This issue arises when I u ...

Facing an issue where the CSS class name is not displaying correctly when utilizing CSS Modules with my React

This webpack.config.js file is dedicated to the module section, where loaders are defined for JSX files and CSS. module: { loaders: [ { test: /\.jsx?$/, exclude: /node_modules/, loader: 'bab ...

Expand the image to fill the entirety of the viewing area

Check out my development website. Whenever you click on an image, a photo slider (using photoswipe) pops up. Is there any way to have the image fill the entire viewport? I attempted using height: 100vh, width: auto, but it didn't work. https://i.ssta ...

Changes are not being detected in new Angular 2 files

Currently, I am enhancing an Angular 2 project by incorporating new modules. However, the changes I made in these files are not being recognized within the project. I have attempted to research how change detection functions in Angular 2, but have not bee ...

Adjust the dimensions of the thead, tbody, and td elements on the fly

I've implemented this property in a .css file on the table shown below and there are 9 records. .fixed tbody td, thead th { width: 5.2%; float: left; } In my scenario, when there are 4 columns, the width should be 23.2%; for 5 columns ...