admin管理员组文章数量:1317572
I'm trying to place labels as element with position:absolute;
over a THREE.JS scene. The problem is that when the mouse is over one of the labels (the red box in the exemple below), the events triggering OrbitControls are "stopped" by the labels and do not propagate to the Renderer.
I've reproduced a minimal version of code to see the problem.
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
margin: 0px;
overflow: hidden;
}
#overlay {
position: absolute;
top: 40%;
left: 40%;
width: 20%;
height: 20%;
background-color: #f00;
padding: 3%;
text-align: center;
color: #fff;
box-sizing: border-box;
}
</style>
</head>
<body>
<div id="container"></div>
<!-- This div below stop the OrbitControls events, why? -->
<div id="overlay">I am a div with position:absolute</div>
<script src=".js/87/three.min.js"></script>
<!-- .js/r87/examples/js/controls/OrbitControls.js -->
<script src="orbit-controls.js"></script>
<script>
var container;
var camera, scene, renderer;
var uniforms, material, mesh;
var controls;
init();
animate();
function init() {
container = document.getElementById('container');
var aspect = window.innerWidth / window.innerHeight;
camera = new THREE.PerspectiveCamera(45, aspect, 0.1, 1500);
camera.position.set(1, 1, 1);
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer();
container.appendChild(renderer.domElement);
renderer.setSize(window.innerWidth, window.innerHeight);
controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshBasicMaterial({
color: 0x00ff00
});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
renderer.render(scene, camera);
}
</script>
</body>
</html>
Here is a link to a similar project where the labels doesn't stop the propagation of the event so that the camera can follow the mouse interaction. However I have not found what makes this exemple work and mine not.
What to do so that the OrbitControls still works behind the <div>
labels ?
I'm trying to place labels as element with position:absolute;
over a THREE.JS scene. The problem is that when the mouse is over one of the labels (the red box in the exemple below), the events triggering OrbitControls are "stopped" by the labels and do not propagate to the Renderer.
I've reproduced a minimal version of code to see the problem.
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
margin: 0px;
overflow: hidden;
}
#overlay {
position: absolute;
top: 40%;
left: 40%;
width: 20%;
height: 20%;
background-color: #f00;
padding: 3%;
text-align: center;
color: #fff;
box-sizing: border-box;
}
</style>
</head>
<body>
<div id="container"></div>
<!-- This div below stop the OrbitControls events, why? -->
<div id="overlay">I am a div with position:absolute</div>
<script src="https://cdnjs.cloudflare./ajax/libs/three.js/87/three.min.js"></script>
<!-- https://raw.githubusercontent./mrdoob/three.js/r87/examples/js/controls/OrbitControls.js -->
<script src="orbit-controls.js"></script>
<script>
var container;
var camera, scene, renderer;
var uniforms, material, mesh;
var controls;
init();
animate();
function init() {
container = document.getElementById('container');
var aspect = window.innerWidth / window.innerHeight;
camera = new THREE.PerspectiveCamera(45, aspect, 0.1, 1500);
camera.position.set(1, 1, 1);
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer();
container.appendChild(renderer.domElement);
renderer.setSize(window.innerWidth, window.innerHeight);
controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshBasicMaterial({
color: 0x00ff00
});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
renderer.render(scene, camera);
}
</script>
</body>
</html>
Here is a link to a similar project where the labels doesn't stop the propagation of the event so that the camera can follow the mouse interaction. However I have not found what makes this exemple work and mine not. http://armsglobe.chromeexperiments.
What to do so that the OrbitControls still works behind the <div>
labels ?
-
1
Try this:
controls = new THREE.OrbitControls(this.camera);
. By default,domElement
will bedocument
– prisoner849 Commented Oct 10, 2017 at 12:51 - Thanks @prisoner849! It fixes the problem. You wanna write the answer or should I do it ? – Ben Commented Oct 10, 2017 at 12:56
-
2
you might want to add
pointer-events: none;
to the css of the overlay-element, that would fix the issue as well – Martin Schuhfuß Commented Oct 10, 2017 at 13:00 -
Event better solution @MartinSchuhfuß. Changing the domElement of the renderer fixes the overlay problem but causes other issues with the camera linked to OrbitControls in my project. The
pointer-events: none;
works best. Just need to be careful about browser patibility. – Ben Commented Oct 10, 2017 at 13:38 - @MartinSchuhfuß any chance to have a similar solution but allowing for "click" event on labels? – Ben Commented Oct 10, 2017 at 20:52
2 Answers
Reset to default 6To summarize answers from ments:
If you don't need any mouse-events from the overlays, it is easiest to just disable event-handling via css:
<div class="overlay" style="pointer-events: none">...</div>
You can also use a mon parent-element for event-handling:
<div class="parent" style="position:relative">
<canvas ... /> <!-- this is the canvas from renderer.domElement -->
<div class="overlay"></div>
</div>
and for the controls
const controls = new THREE.OrbitControls(camera, document.querySelector('.parent'));
this way all mouse-events reaching the parent (which includes events from the overlays) will be handled by the controls (a special case of this is handling all events at the root-level, by omitting the dom-element (or specifying document.documentElement
) for the OrbitControls constructor).
If you want to handle certain events from the overlays, like click for instance, you can prevent them to get forwarded to the orbit-controls using stopPropagation()
:
overlayEl.addEventListener('click', event => {
event.stopPropagation();
// handle event
});
If you want to apply orbit controls on the background scene you can do this:
const controls = new orbitControls.OrbitControls(camera, document.body);
版权声明:本文标题:javascript - THREE.JS OrbitControls not working when DOM Element is positioned over the scene - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742020838a2414641.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论