Ways to avoid the cascading of CSS styles onto multiple Three.JS scenes

It seems like I might have to take the longer route to solve this issue, but let's give it a shot...

I'm facing a challenge when applying CSS to control the opacity of a specific HTML element that acts as a container for a Three.JS scene. In this scenario, there are multiple elements, each serving as containers for their respective scenes. The problem arises when the CSS attributes (even when applied inline) intended for one specific scene-containing element end up being applied to all elements containing scenes, rather than just the targeted one. This phenomenon occurs not only with opacity but with any post-applied CSS attribute.

The reason behind this workaround is that, based on my research, there's no direct method to set opacity on a Three.JS group object that houses multiple meshes. I am attempting - in theory - to avoid defining every material with transparency enabled and then recursively updating all meshes within a Three.JS Group object for a fade in/out animation.

Some of these group objects contain numerous meshes. Instead of individually updating the opacity of each mesh within a Three.JS Group object, my intention was/is to create separate scenes for different animations, allowing for customizable levels of transparency, and simply adjusting the opacity property of the HTML element containing that particular animation.

I've experimented with using both single and multiple cameras without success. I also attempted nesting the containers under an additional element and setting CSS on the parent element, but encountered the same issue. While I haven't explored the option of using multiple renderers, my research indicates potential performance concerns and context limitations associated with this approach. Furthermore, the render loop has "autoClear" disabled to ensure all scenes render simultaneously.

Below is the HTML structure. Note that the first element includes an inline style setting opacity to 0.5, while the second element has no inline styling:

<div class="three-js-container" id="scene-container-1" style="opacity:0.5;"></div>
<div class="three-js-container" id="scene-container-2"></div>

Below is the corresponding Javascript code:

/* Only one renderer instance is created */
var universalRenderer = new THREE.WebGLRenderer({antialias: true, alpha:true});

/* references to all containers are made */
var containerForScene1 = document.getElementById("scene-container-1");
var containerForScene2 = document.getElementById("scene-container-2");

/* two different cameras are created */
var cameraForScene1 = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.001, 1000);
var cameraForScene2 = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.001, 1000);

/* two different scenes are created, one for each element container */
var scene1 = new THREE.Scene();
scene1.userData.element = containerForScene1;

var scene2 = new THREE.Scene();
scene2.userData.element = containerForScene2;

/* the renderer is applied to both scene containers */
containerForScene1.appendChild(universalRenderer.domElement);
containerForScene2.appendChild(universalRenderer.domElement);

Upon playing both animations, both scenes appear at half-opacity instead of just the intended first scene. Why does CSS styling applied to one HTML scene-containing element affect all other scene-containing elements? Must I resort to manually controlling mesh opacity?

Appreciate your insights.

Answer №1

Learn how to set transparency on a THREE.Group:

In Three.js, a Group acts as a container for objects. While you cannot directly apply transparency to a Group, you can achieve this by manipulating the Material assigned to the individual children within the group. One approach is to use a technique called monkey patching to enable transparency settings on a Group.

// Apply Monkey Patch for Transparency
Object.defineProperty(THREE.Group.prototype, "transparent", {
  set: function(newXP) {
    this.traverse(node => {
      if (node.material) {
        node.material.transparent = newXP
        node.material.opacity = (newXP) ? 0.5 : 1
      }
    })
  }
})

// Set up the renderer and scene

const renderer = new THREE.WebGLRenderer({
  alpha: true,
  antialias: true
})
document.body.appendChild(renderer.domElement)

renderer.setSize(window.innerWidth, window.innerHeight)

const scene = new THREE.Scene()

const size = new THREE.Vector2()
renderer.getSize(size)
const camera = new THREE.PerspectiveCamera(28, size.x / size.y, 1, 1000)
camera.position.set(0, 20, 100)
camera.lookAt(scene.position)
scene.add(camera)

camera.add(new THREE.PointLight(0xffffff, 1))

function render() {
  renderer.render(scene, camera)
}

const axis = new THREE.Vector3(0, 1, 0)

function animate() {
  requestAnimationFrame(animate)
  camera.position.applyAxisAngle(axis, 0.005)
  camera.lookAt(scene.position)
  render()
}
animate()

// Add cube objects to the scene with different materials

const cubeGeometry = new THREE.BoxBufferGeometry(5, 5, 5)

let opaqueCubes = []
let transparentCubes = []

const getRandomPosition = () => Math.random() * ((Math.random() <= 0.5) ? -10 : 10)

const opaqueGroup = new THREE.Group()
scene.add(opaqueGroup)
for (let i = 0; i < 10; ++i) {
  opaqueGroup.add(new THREE.Mesh(cubeGeometry, new THREE.MeshPhongMaterial({
    color: "red"
  })))
  opaqueGroup.children[i].position.set(getRandomPosition(), getRandomPosition(), getRandomPosition())
}

const transparentGroup = new THREE.Group()
scene.add(transparentGroup)
for (let i = 0; i < 10; ++i) {
  transparentGroup.add(new THREE.Mesh(cubeGeometry, new THREE.MeshPhongMaterial({
    color: "green"
  })))
  transparentGroup.children[i].position.set(getRandomPosition(-10, 10), getRandomPosition(-10, 10), getRandomPosition(-10, 10))
}

// Control transparency using input checkbox

const xparent = document.getElementById("xparent")
xparent.addEventListener("change", (e) => {
  transparentGroup.transparent = xparent.checked
})
html,
body {
  padding: 0;
  margin: 0;
  overflow: hidden;
}

#control {
  position: absolute;
  top: 0;
  left: 0;
  padding: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/105/three.js"></script>
<div id="control">
  <label>Make the green cubes transparent:<input id="xparent" type="checkbox" /></label>
  <div>

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

What is the best approach to achieve the old THREE.SpriteAlignment effect in the latest version of three.js?

After adapting an old three.js code for my application that includes a 3D function with axes grids, I encountered an issue when trying to update it to the latest revision, r74: https://jsfiddle.net/cjfwg2c4/ Without THREE.SpriteAlignment.topLeft, sprites ...

Enhancing Bootstrap project with personalized CSS styling

Utilizing SCSS to create my CSS has been the approach I've taken. The content of my main.scss file remains consistent even after it is compiled into css. .my-custom-row { background-color: bisque; } Contained within my index.html file is everythi ...

Drop-down and autocomplete feature in Material UI design framework

Encountering an issue with aligning a label with a dropdown in material UI, and for some reason, this behavior is observed: https://i.sstatic.net/n7pj8.png Struggling to get them aligned on the same row. This is the code snippet of my component: const us ...

Enhancing image clips using jQuery techniques

Could someone help me figure out why the image clip value isn't changing when I move the range slider in the code below? $('#myRange').on('input', function() { var nn = $(this).val(); $("img").css({ 'clip': ...

Tapping on a DIV element that overlays a YouTube video on an iPad does not trigger any action

Currently, I am working on a webpage specifically designed for iPad and I have encountered an issue: I am trying to embed a YouTube video using an iframe and also need a div element to remain on top of it. To achieve this, I have added "?wmode=transparen ...

Vuetify: how to disable the color transition for v-icon

My menu includes both icon and text items, with hover color styled using the following CSS: .v-list-item:hover { background: #0091DA; } .v-list-item:hover .v-list-item__title, .v-list-item:hover .v-icon { color: white; } The problem is that the ...

Applying different styling to the same class within a different element using the + selector

Have you ever come across a website with code similar to what I've shared on this jsfiddle: https://jsfiddle.net/roa8k7js/ This particular site boasts an elaborate CSS styling sheet, exceeding 10,000 lines in length. When transitioning this website t ...

Determining the height of a jQuery mobile page

Struggling for the last 24 hours to adjust the min-height styling on a jQuery mobile page specifically for mobile safari. Despite trying various methods like inline styles and overriding ui-page styles, I have not been successful in changing the height of ...

Unknown CSS element discovered: bootstrap, gradient, carousel

I recently created a random quote app using javascript, jQuery, and bootstrap on Codepen. Everything worked perfectly there. However, when I organized the files, pushed them to git, and tried to view the app from Safari, I encountered some warnings and t ...

Minimize the entire project by compressing the .css, .js, and .html files

After recently incorporating Grunt into my workflow, I was thrilled with how it streamlined the process of minifying/concatenating .css files and minifying/uglify/concatenating .js files. With Grunt watch and express, I was able to automate compiling and ...

What methods can I implement to prevent my boxes from becoming stretched out?

How can I prevent this box from stretching too much? Here is the code snippet along with the output: CSS: .social { padding-left: 1000px; border: 5px inset black; margin: 4px; width: 100px; } HTML: <div class="social"> <p& ...

Optimizing animations in Three.js with skeleton recalculations

I'm curious about how to blend skeletal animations. Specifically, I have a walking animation and want to adjust the arm position within it. My understanding is that I'll need to recalibrate the arm's position in each keyframe. Is this standa ...

Ensuring Your IMG is Perfectly Centered in DIV Across all Browsers

I have tried all the tips from the top Google results, but I am still struggling to center an image within a div. For example, the popular tricks mentioned in this link: or http://www.w3.org/Style/Examples/007/center.en.html do not seem to work in IE 8. ...

Tips for keeping my background image from shrinking when I resize the window?

When I resize the webpage window, my background image shrinks in size. Currently, it is not repeating (which is a step forward), but now I need it to cover the entire screen to avoid showing white space around the background when the window gets smaller. ...

What is the most effective method for embedding a Kotlin program into a website?

I have created a combat simulation tool in Kotlin for an online gaming community. Users can input the combat levels of two players, choose the number of duels to simulate, and then initiate the simulation which will provide win percentages and other stats. ...

RectAreaLight in Three js does not produce any light reflection when used with MeshPhongMaterial due to lack of support for OES_texture_half

After trying to incorporate a RectAreaLight into my three.js scene where I have objects with MeshPhongMaterial, I noticed that there is no light reflection on the objects. A useful example can be found here: Link If you open the developer tools, you can s ...

Embracing the HTML5 Approach to iframes

My question pertains to iframes - I am looking to apply styling to the contents of an iframe using only CSS within the srcdoc attribute. <iframe name="myFrame" srcdoc="<span>Hi</span>"> </iframe> Is it feasible to style the span e ...

Displaying a div upon hovering over another div is resulting in numerous server requests and a flickering effect

I am attempting to create a hover effect where one div floats next to another. The layout of the divs is like a grid, placed side by side. Check out my code on this fiddle. Using plain JavaScript, I want to display a second div (div2) floating next to div ...

Is there a way to eliminate the gap between two horizontal rule tags?

What causes the space between two <hr> tags to remain? Despite setting the width of the <hr> tags to 49%, there is still a gap between them. How can this space be removed from the <hr> tags? Shown below is the HTML and CSS code: *{mar ...

Retrieve information from the database and showcase it in a competitive ranking system

Here is the HTML and CSS code for a leaderboard: /* CSS code for the leaderboard */ To display the top 5 in the leaderboard, PHP can be used to fetch data from the database: <?php // PHP code to retrieve data from the database ?> The current ou ...