避免将按键事件从 dat.GUI 传播到 Three.js 场景
Avoid propagating keydown events from dat.GUI to Three.js scene
我有这段代码(见下文)和 2 个事件侦听器:
renderer.domElement.addEventListener("pointerdown", changeColor, false);
document.addEventListener("keydown", changeColor, false);
它们都会触发立方体的颜色变化。但是,当我在 GUI 中编辑输入参数时,keydown
事件也会导致颜色发生变化,我想避免这种情况。
我猜这是因为我在 keydown
事件中使用 document.addEventListener
。但是,如果我改用 renderer.domElement.addEventListener
,它将不起作用。
编辑 GUI 参数时如何避免 keydown
事件传播?
代码
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/three@0.126.0/build/three.min.js"></script>
<script src="https://unpkg.com/three@0.126.0/examples/js/controls/OrbitControls.js"></script>
<script src="https://stemkoski.github.io/Three.js/js/DAT.GUI.min.js"></script>
</head>
<body>
</body>
</html>
不确定这是最好的方法,但您可以通过检查事件处理程序的目标来忽略来自事件处理程序的按键事件。如果目标是 input
,则什么都不做:
function changeColor(event) {
// Ignore key event when editing dat.GUI input values
if (event.target.localName == "input") {
return;
}
// [...]
}
我有这段代码(见下文)和 2 个事件侦听器:
renderer.domElement.addEventListener("pointerdown", changeColor, false);
document.addEventListener("keydown", changeColor, false);
它们都会触发立方体的颜色变化。但是,当我在 GUI 中编辑输入参数时,keydown
事件也会导致颜色发生变化,我想避免这种情况。
我猜这是因为我在 keydown
事件中使用 document.addEventListener
。但是,如果我改用 renderer.domElement.addEventListener
,它将不起作用。
编辑 GUI 参数时如何避免 keydown
事件传播?
代码
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/three@0.126.0/build/three.min.js"></script>
<script src="https://unpkg.com/three@0.126.0/examples/js/controls/OrbitControls.js"></script>
<script src="https://stemkoski.github.io/Three.js/js/DAT.GUI.min.js"></script>
</head>
<body>
</body>
</html>
不确定这是最好的方法,但您可以通过检查事件处理程序的目标来忽略来自事件处理程序的按键事件。如果目标是 input
,则什么都不做:
function changeColor(event) {
// Ignore key event when editing dat.GUI input values
if (event.target.localName == "input") {
return;
}
// [...]
}