Avoid mouse interactions listener when hover GUI

I have a simple scene with a cube and a fake GUI:

https://jsfiddle.net/Peque/wxa250ho/

When I click with the mouse, on “mouse-up”, the cube changes color. Now, when I interact with the GUI (move the slider, open/close controls, click on the tag name…), the cube changes color too.

Is there any way I could avoid executing any Three.js interaction when the mouse is hover the GUI?

Edit

Pasting the code here for reference:

var renderer, controls, scene, camera;
var cube;

init();

function init() {

    // Scene
    scene = new THREE.Scene();
    scene.background = new THREE.Color(0xb0b0b0);

    // Camera
    camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 1, 1000);
    camera.position.set(300, 300, 300);
    camera.up.set(0, 0, 1);

    // Light
    var ambientLight = new THREE.AmbientLight(0xcccccc, 0.2);
    scene.add(ambientLight);

    // Helpers
    var helpers = new THREE.Group();
    var grid = new THREE.GridHelper(200, 10);
    grid.rotation.x = Math.PI / 2;
    var axis = THREE.AxisHelper(100);
    helpers.add(grid);
    helpers.add(axis);
    scene.add(helpers);

    // Renderer
    renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    // Controls
    controls = new THREE.OrbitControls(camera, renderer.domElement);

    // Event listeners
    controls.addEventListener("change", render, false);

    // Draw the cube
    var cubeGeometry = new THREE.CubeGeometry( 50, 50, 50 );
		var cubeMaterial = new THREE.MeshBasicMaterial({ color: 0x000088 } );
		cube = new THREE.Mesh( cubeGeometry, cubeMaterial );
    scene.add(cube);
    
    // GUI
    params = {
    	size: 50,
    };
   	var gui = new dat.GUI();
    gui.add(params, "size", 0.0, 100, 1);
    
    // Listeners
    document.addEventListener("mouseup", onMouseUp, false);

    // Render
    render();
}

function onMouseUp() {
	cube.material.color.set(Math.random() * 0xffffff);
  cube.material.needsUpdate = true;
  render();
}

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

It should work if you add the event listener like so instead:

renderer.domElement.addEventListener("mouseup", onMouseUp, false);

Updated fiddle: https://jsfiddle.net/nauhze7j/

3 Likes

@Mugen87 Thanks a lot! :blush:

I intuitively tried renderer.addEventListener(), but that did not work… :joy:

1 Like

.addEventListener()requires a DOM Element. In other words, some HTML element on the page, like <div>, <img>, <button> etc. WebGL graphics are displayed on a <canvas> element. You can create your own canvas or use the one THREE.WebGLRenderer creates internally, when it’s created - renderer.domElement.

If you add an event listener to the document, then the whole page will react to your event. So it’s a good idea to restrict graphics-related events just to the graphics-related DOM element :slight_smile:
If you look at your code, you’ll notice that when creating THREE.OrbitControls you actually passed the renderer.domElement there as well. Thats why when you drag your mouse on the GUI slider, the orbit controls dont activate and camera stays still :slight_smile:

btw I don’t think changing the material’s color requires setting the .needsUpdate = true flag.

2 Likes