Using Threejs with dropdown menus: Showcasing the chosen model exclusively

I am looking to only show the selected value (in this case, the 3D model) from a dropdown menu. The chosen option should be the only one visible in the camera view. I am encountering some difficulty with the following code segment:

                    const loader = new GLTFLoader().setPath('models/gltf/modeldatabase/');
                for (let i = 0; i < prefabcontainer.length; i++) {

                    let prefabResource = prefabcontainer[i];

                    loader.load(prefabResource, function (gltf) {

                        object = gltf.scene;
                        object.scale.set(5, 5, 5);
                        
                        var select = document.getElementById("selectPrefab");
                        prefabResource = prefabResource.replace(/\..+$/, '');
                        var prefabElement = document.createElement("option");
                        prefabElement.textContent = prefabResource;
                        prefabElement.value = prefabResource;
                        select.appendChild(prefabElement);
                        scene.add(object);
                        render();

                    }, undefined, function (error) {
                        console.error(error);
                    })

            }

The 'prefabcontainer' is simply a basic JavaScript script:

let prefabcontainer = [
'shotgun.gltf',
'pistol.gltf'];

export{prefabcontainer};

Here is the HTML snippet involved:

<div><select id="selectPrefab">

Your assistance on this matter is greatly appreciated, thank you!

Answer №1

Create an array outside the loop to store loaded objects and a DocumentFragment to hold the <options> while generating them. This way, only one DOM change is made after all <option>s are generated. Also, move the declaration of select to this scope.

...
+   const select = document.getElementById("selectPrefab");
+   const prefabObjects = [];
+   const fragment = document.createDocumentFragment();
    for (let i = 0; i < prefabcontainer.length; i++) {
         ...
-        var select = document.getElementById("selectPrefab");
...

Modify the line that sets the value of <option> to use the index and set the defaultSelected property on the first <option>. Use the Option(text, value, defaultSelected) constructor[MDN].

...
-   var prefabElement = document.createElement("option");
-   prefabElement.textContent = prefabResource;
-   prefabElement.value = prefabResource;
-   select.appendChild(prefabElement);
+   const prefabElement = new Option(prefabResource, i, i === 0);
+   fragment.appendChild(prefabElement);
...

Create a function to change the visible property on a Three.js Object3D and its children.

function traverseSetVisible(startObject, visible) {
    startObject.traverse(function(obj) {
        if(obj.isObject3D) {
            obj.visible = visible;
        }
    });
}

Add the loaded object to the previously declared array. Set the visible property to false on the second and subsequent objects. Conditionally call render() when dealing with the first object.

...
    fragment.appendChild(prefabElement);
+   prefabObjects.push(object);
+   if (i !== 0) {
+       traverseSetVisible(object, false);
+   }
    scene.add(object);
-   render();
+   if (i === 0) {
+       render();
+   }
...

Outside the loop, add the generated <option>s fragment to the <select>. Include an event listener to handle selections in the drop-down by toggling the visible state of the prefabs.

     } // end of for loop
+    select.appendChild(fragment);
+    select.addEventListener('change', function() {
+         const selectedValue = parseInt(select.Value);
+         for (let i = 0; i < prefabObjects.length; i++) {
+              const visible = i === selectedValue;
+              traverseSetVisible(prefabObjects[i], visible);
+         }
+         render();
+    }

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

"Encountering errors when attempting to load partials on the server-side

Currently, I am working on creating a basic single page application using the MEAN stack. Everything was running smoothly when I was developing on localhost. However, upon uploading the code to the server, I encountered a status code 500 (Internal Server ...

Non-reactive arrays in Vue.js

I am facing an issue. Here is the problem: data: { tracks: [] } The tracks array will contain a complex object. I want to achieve reactivity when assigning a new value to tracks nested object, but I do not need deep reactivity for the object. ...

Error Alert: Unresponsive JQuery Script

Currently, I am in the process of developing a website that requires a significant amount of script work. However, we are experiencing browser hang-ups and unresponsive script errors due to the extensive data load while loading listings for YouTube. The d ...

You must use the 'new' keyword to invoke the class constructor NextResponse | Implementing middleware in Next.js | Implementing role-based protection for routes in Next.js |

I've been working on implementing user role-based protected routes in my next.js project using middleware.js, but all of a sudden, I've encountered this issue. I'm not exactly sure why this is happening, so if anyone has a better approach to ...

javascript/node Struggle with JSON parsing

Here is some sample data: I am currently building a node application that extracts information from the provided link. Specifically, I am interested in sets, set, and song details. var sets = setlist.sets res.write(JSON.stringify(sets)) // DISPLAYS THE C ...

Having more than one bootstrap modal on a single page is not supported

I'm stuck and can't figure it out. I have multiple triggers that are very similar <a style="margin: 4px 4px 4px 4px !important" data-toggle="modal" data-target="#video_modal" data-title="YouTube v ...

What is the process for generating a tree structure from an HTML element?

This particular element is found within my Vue2 application: <div class="child-elements-container draggable-container"> <div> <div entity-type="entitytype1" type="elementType" id="2" class= ...

Exclude objects with similar ids using a method other than JavaScript's filter()

I have a list of students who need to receive medication multiple times throughout the day. The challenge is to filter the array to track how many times each student receives the same medication. The list includes three different students and repeats the s ...

Stop the ongoing ajax request, initiate a new one, and then resume the initial ajax call

There's some doubt in my mind about whether this can be done. During a button click event, I am making two ajax calls. The first call uses jQuery ajax post to add data to the database, and the second call does the same with a different set of data. ...

"Failure to update variables within the catch block of the .map() function leads to inconsistencies

Greetings Sorcerers, I have been utilizing .map() to loop through an array of Objects. Following some data manipulations and assigning values to specific variables, I am inserting them into a postgres database. const insertIntoDB = (jsonObj) => { le ...

Unconventional login processes showcased in Redux-Saga's documentation

When looking at the login flow example in the redux-saga documentation, it is clear that the expected action sequence is well-defined. However, does the LOGOUT action always follow the LOGIN action? In real-world scenarios, such as when a user's sessi ...

What is the best way to position an image on top of a circular object?

I have a circle variable that I'm using in a canvas game. How can I add an image on top of it while still allowing the circle to move around the canvas? var img = new Image(); img.src = "img.png"; var ball = { radius: 0 ,position: { x: 0, ...

Encountered a SyntaxError stating 'Unable to use import statement outside a module' while attempting to utilize three.js

I'm facing difficulties with incorporating three.js into my project. Initially, I executed: I am referring to the guidelines provided here: In my VS Code terminal for the project folder, I ran the following command: npm install --save three Subsequ ...

The iFrame that is generated dynamically becomes null when accessed from a page that has been loaded using JQuery

One issue I am facing is with a dynamically created iframe in regular javascript. It functions perfectly fine when called from a static page using conventional methods. However, when it is being called from a page loaded by jQuery, I encounter an error s ...

Problem encountered when using ".replace()" function

Is there a way I can modify my existing code to handle the use of `` within replace? Currently, due to being inside a loop .each, it correctly identifies the word but then wraps it with <span></span> multiple times. I would like it to apply the ...

I am having trouble with my React tutorial for tic tac toe as the handleClick function is not receiving the

Currently, I am working my way through the React tutorial available at: https://react.dev/learn/tutorial-tic-tac-toe My current challenge lies in passing a value to the handleClick function to determine which square should be set to 'X'. Despi ...

Margins are added to cards on the right side

Looking for some help to improve the display of three cards in a grid. The card media has a max-width of 345px, but this is causing excessive margin-right space and making the styling look poorly. Any suggestions on how to eliminate this extra margin? If ...

Utilizing Node and Express to promptly respond to the user before resuming the program's

I am accustomed to receiving a user's request, handling it, and providing the outcome in response. However, I am faced with an API endpoint that requires about 10 tasks to be completed across various databases, logging, emailing, etc. All of these ta ...

Make sure that the TextBox OnTextChanged event in ASP.NET triggers a "setTimeout" function before the OnClick event is fired

Imagine the following situation: <asp:TextBox ID="txt" runat="server" AutoPostBack="true" OnTextChanged="txt_TextChanged"></asp:TextBox> <asp:Button ID="btn" runat="server" OnClick="btn_Click" CausesValidation="false" UseSubmitBehavior="fal ...

What is the process for inserting specific characters between JavaScript date values?

In my JavaScript project, I am attempting to adjust the date format to a specific style. The format I aim for is 29-Jan-2021. Currently, with the code below, I can generate "29 Jan 2021": var newDate = new Date('2021-01-29T12:18:48.6588 ...