A guide on utilizing a looped event listener with a function to switch object textures in THREE.JS

Currently working on a Webgl 3D project, the task at hand is to dynamically change the textures of a loaded COLLADA object by clicking on buttons associated with each texture.

Up until now, I've successfully achieved this with three textures by duplicating the same code thrice. However, this approach raises the following question:

How can I streamline the process by using a single event listener to handle changes for any number of textures I may have?

***** MY EXISTING CODE BELOW FUNCTIONS CORRECTLY *****

Below are snippets of my code:

<button type="submit" id="wd1" onclick="setMat1()" ><img src='tex/wd1.png'/></button>
<button type="submit" id="wd2" onclick="setMat2()"><img src='tex/wd3.png'/></button>
<button type="submit" id="wd3" onclick="setMat3()"><img src='tex/wd2.png'/></button>

And

function setMat1 () {
 elf.traverse(function(child) {
 if (child instanceof THREE.Mesh){
     var mat1 = textureLoader.load('obj/tex/wood3.png');
     child.material.map = mat1;
 }
 elf.needsUpdate=true;
 });
 }

 function setMat2 () {
 elf.traverse(function(child) {
     if (child instanceof THREE.Mesh){
         var mat2 = textureLoader.load('obj/tex/wood5.png');
         child.material.map = mat2;
     }
     elf.needsUpdate=true;
 });
 }
            
 function setMat3 () {
 elf.traverse(function(child) {
 if (child instanceof THREE.Mesh){
     var mat3 = textureLoader.load('obj/tex/wood4.png');
     child.material.map = mat3;
 }
 elf.needsUpdate=true;
 });
 }

I decided to post this query here as I plan to incorporate at least 20 additional textures, and implementing them in the manner I currently have doesn't seem like the most efficient solution :)

Answer №1

Perhaps this coding snippet could work for your purpose:

function setMat(matUrl) {
 new THREE.TextureLoader().load(matUrl,(tex)=>{
     scene.traverse(function(child) {
         if (child instanceof THREE.Mesh){
             child.material.map = tex;
             child.material.needsUpdate = true;
         }
     });
 });
}

-OR- a more concise alternative below that extracts the URL from the source of the clicked image...

var renderer = new THREE.WebGLRenderer();
var w = 300;
var h = 200;
renderer.setSize(w, h);
document.body.appendChild(renderer.domElement);

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
  45,
  w / h,
  0.1,
  10000
);
camera.position.set(15, 10, 15);
camera.lookAt(scene.position);
controls = new THREE.OrbitControls(camera, renderer.domElement);

var light = new THREE.PointLight(0xFFFF00);
light.position.set(20, 20, 20);
scene.add(light);
var light1 = new THREE.AmbientLight(0x808080);
light1.position.set(20, 20, 20);
scene.add(light1);
var light2 = new THREE.PointLight(0x00FFFF);
light2.position.set(-20, 20, -20);
scene.add(light2);
var light3 = new THREE.PointLight(0xFF00FF);
light3.position.set(-20, -20, -20);
scene.add(light3);

var sphereGeom = new THREE.SphereGeometry(5, 16, 16);
var material = new THREE.MeshLambertMaterial({
  color: 0x808080
});
var mesh = new THREE.Mesh(sphereGeom, material);
scene.add(mesh);
renderer.setClearColor(0xdddddd, 1);

function setMat(evt) {
  var src = evt.target.src ? evt.target.src : evt.target.children[0].src;
  new THREE.TextureLoader().load(src, (tex) => {
    scene.traverse(function(child) {
      if (child instanceof THREE.Mesh) {
        child.material.map = tex;
        child.material.needsUpdate = true;
      }
    });
  });
}

var buttons = document.getElementsByTagName('button'); 
for(var i=0;i<buttons.length;i++)buttons[i].onclick = setMat;
(function animate() {
  requestAnimationFrame(animate);
  controls.update();
  renderer.render(scene, camera);
})();
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>

<button><img src="https://media.giphy.com/media/xThuWg7lusylvpAVu8/giphy.gif" width=100 height=100 >1</img></button>

<button><img src="https://res.cloudinary.com/teepublic/image/private/s--gWNjhADC--/t_Preview/b_rgb:262c3a,c_limit,f_auto,h_313,q_90,w_313/v1508184648/production/designs/1977157_1" width=100 height=100 >2</img></button>

<button><img src="https://media.giphy.com/media/xThuWg7lusylvpAVu8/giphy.gif" width=100 height=100 >3</img></button></br>

Answer №2

To update the content, simply include the following code:

child.content.update = true;
child.content.media.update = true;

For more detailed examples, you can visit this link

and also check out

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

Using Angular to open a modal by invoking the href function

Current Project Context I am currently following a tutorial on CRUD operations with DataTables, but I am using Asp.Net WebApi with Angular for this project. At step 9 of the tutorial, it introduces partial views for pop-up windows. However, instead of us ...

How can you determine if a table cell's property of "disable" is set to true or false using jQuery?

Every time I add a new row by clicking the addNewRow button, I make sure to validate all input cells in that row. Then, after clicking the "CompletedBtn," the row becomes disabled. However, when I try to edit a specific row by clicking the editBtn, I wan ...

Enhance Odoo Conversations (mail)

I've been attempting to customize the Odoo discussions, but have hit a roadblock. Here is my goal: https://i.sstatic.net/1lJnc.png I am adding messages using the "New Message" button to an Odoo module (in class mro.order). The messages are appearing ...

How to stop Mouseenter event from bubbling up in an unordered list of hyperlinks using Vue 3

I've experimented with various methods to prevent event bubbling on the mouseenter event, but I'm still encountering an issue. When I hover over a link, the event is triggered for all the links as if they were all being hovered over simultaneousl ...

Comparison: executing an immediately invoked function expression (IIFE) and a separate

During my recent refactoring of some legacy code, I stumbled upon the following example: // within another function const isTriggerValid = await (async () => { try { const triggers = await db.any(getTriggerBeforeBook, { param ...

Return to the previous page without refreshing the page

Is there a way to add a back button on the user form detail page that redirects the user back to the previous page without triggering a reload? Currently, when I click the back button in the browser, it reloads the list of users. I'd like to avoid th ...

Hover over the div to center an SVG inside it

Simply put, I am working on a design where a gradient bar moves above a specific element when hovered, creating a visual effect of a triangle. I am now looking for a way to center an SVG inside the element on hover, to create a similar triangular gradient ...

The values returned by a NodeJS script in the Python shell are identical to those returned by Node

The following program was developed to address an issue in another application. In this program, a Python script is called from Node.js to perform a task. The Python script returns results that are then used in Node.js. NodeJS : var pythonShell = require ...

Retrieving POST data in Ajax requests

I am currently using an ajax-based commenting system. This system is set up to create a div section for comments and a reply box through a php loop, which results in the form being duplicated multiple times. How can I ensure that the variable 'parent ...

Presenting data fetched from Firebase database in an HTML table format

I recently started working with Firebase and I'm attempting to fetch static data from my Firebase Database to showcase in a tabular format on an HTML page. Below is the structure of the HTML code I've implemented: <section> <table> ...

Concealing the map on the webpage using Javascript (iframe)

Here is an excerpt from my code: <div id='content'> <div id='map'></div> <iframe name="content-wrapper"></iframe> </div> <div class="sidebar"> <div class="container"> <h2 ...

How do I use React and Material-UI to efficiently display multiple tables from a complex JSON object containing multiple arrays of data?

Trying to come up with an innovative approach to generate a unique dynamic table component that can create individual tables based on the number of arrays in a dictionary object (essentially iterating through each array and generating a table). For my sce ...

Issue with triggering submit handler twice in React JS

Just starting out with React and I'm trying to create a submit form in a modal, but I'm facing an issue. The form includes a textbox and multiple checkboxes (array object). When I check one of these checkboxes, it should add a new key (IsChecked ...

Obtain the date in ISO format without subtracting the timezone offset

I need to obtain a Date string without the timezone being added or subtracted. Currently, when I set my OS timezone to GMT +13 and create a new Date() object, the toISOString() method subtracts one day. For example, today is 11/02. If I adjust my OS time ...

I would like a div element to slide up from the bottom of the page

Could someone please assist me in creating a popup div that appears from bottom to top when a specific button is clicked? I would like the div to be fixed without affecting the overall page content. Any help would be greatly appreciated. Thank you! $( ...

Is there a way for me to retrieve form information?

I have encountered a challenge with my React app. The login form data appears to be empty when I attempt to send it to the backend. // Login component class submitLoginForm = (event) => { event.preventDefault(); const target = event.target; ...

The replace() function is failing to replace the provided inputs

Supposedly, when a user types in certain profanity and submits it, the word is supposed to be replaced with a censored version. Unfortunately, this feature is not working as expected. The word appears uncensored. Do you think implementing if/else stateme ...

Display a "busy" indicator using Ajax, specifically for requests that take longer to process

Is there a way to delay the appearance of the busy indicator until a certain amount of time has passed? The code I'm using for the busy indicator is quite simple: jQuery.ajaxSetup( { beforeSend:function () { jQuery( "#busy-indicator" ...

What is the best way to store a collection of objects generated from an AJAX request that retrieves information from a JSON file using JavaScript?

I have successfully retrieved my JSON objects using the code snippet below. After logging the variable "value2", I can confirm that the values are being displayed in my console. However, I am encountering an issue where my "arraytest" remains empty even af ...

Access and retrieve data from a string using XPath with JavaScript

My HTML page content is stored as a string shown below: <!DOCTYPE html> <html> <head> <title>Page Title</title> </head> <body> <h1>This is a Heading</h1> <p>This is a paragraph.</p> </ ...