Avoid propagating keydown events from dat.GUI to Three.js scene

418 views Asked by At

I have this code (see bellow) with 2 event listeners:

renderer.domElement.addEventListener("pointerdown", changeColor, false);
document.addEventListener("keydown", changeColor, false);

They both trigger a color change in the cube. However, when I edit the input parameter in the GUI, keydown events also result in a color change, and I would like to avoid that.

I am guessing this is because I am using document.addEventListener for the keydown events. However, if I use renderer.domElement.addEventListener instead it wont work.

How can I avoid keydown events to propagate when editing GUI parameters?

Code

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.BoxGeometry( 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
    renderer.domElement.addEventListener("pointerdown", changeColor, false);
    document.addEventListener("keydown", changeColor, false);

    // Render
    render();
}

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

function render() {
    renderer.render(scene, camera);
}
body {
  overflow: hidden;
  margin: 0;
}
<html>
    <head>
        <script src="https://unpkg.com/[email protected]/build/three.min.js"></script>
        <script src="https://unpkg.com/[email protected]/examples/js/controls/OrbitControls.js"></script>
        <script src="https://stemkoski.github.io/Three.js/js/DAT.GUI.min.js"></script>
    </head>
    <body>
    </body>
</html>

1

There are 1 answers

0
Peque On BEST ANSWER

Not sure this is the best approach, but you can ignore keydown events from the event handler by inspecting its target. If the target is an input, then do nothing:

function changeColor(event) {
    // Ignore key event when editing dat.GUI input values
    if (event.target.localName == "input") {
        return;
    }
    // [...]
}