Reputation: 277
I have a full window three.js scene. I have some absolutely positioned buttons on top of the scene and off to the side. If you click and drag the camera spins (weee!) but if you drag over the buttons the spinning stops (boo). It also stops if you drag out of the window. I'm using three.js R76 and OrbitControls.js. Is there an easy way to get the scene to keep listening to the mouse movement while the button is still held down?
http://codepen.io/anon/pen/qZgEBN HTML
<html lang="en">
<head>
<title>three.js webgl - orbit controls</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
color: #000;
font-family:Monospace;
font-size:13px;
text-align:center;
font-weight: bold;
background-color: #fff;
margin: 0px;
overflow: hidden;
}
#info {
color:#000;
position: absolute;
top: 0px; width: 100%;
padding: 5px;
}
a {
color: red;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info">
<a href="http://threejs.org" target="_blank">three.js</a> - orbit controls example
</div>
</body>
JS
var camera, controls, scene, renderer;
init();
animate();
function init() {
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );
renderer = new THREE.WebGLRenderer();
renderer.setClearColor( scene.fog.color );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
var container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 500;
controls = new THREE.OrbitControls( camera, renderer.domElement );
//controls.addEventListener( 'change', render ); // add this only if there is no animation loop (requestAnimationFrame)
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.enableZoom = false;
// world
var geometry = new THREE.CylinderGeometry( 0, 10, 30, 4, 1 );
var material = new THREE.MeshPhongMaterial( { color:0xffffff, shading: THREE.FlatShading } );
for ( var i = 0; i < 500; i ++ ) {
var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = ( Math.random() - 0.5 ) * 1000;
mesh.position.y = ( Math.random() - 0.5 ) * 1000;
mesh.position.z = ( Math.random() - 0.5 ) * 1000;
mesh.updateMatrix();
mesh.matrixAutoUpdate = false;
scene.add( mesh );
}
// lights
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 1, 1, 1 );
scene.add( light );
light = new THREE.DirectionalLight( 0x002288 );
light.position.set( -1, -1, -1 );
scene.add( light );
light = new THREE.AmbientLight( 0x222222 );
scene.add( light );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
controls.update(); // required if controls.enableDamping = true, or if controls.autoRotate = true
render();
}
function render() {
renderer.render( scene, camera );
}
If you click and drag to spin the camera it works so long as you're in the actual scene but if your mouse goes outside of the scene the spinning stops. I'd like it to continue to spin.
Side note: the codepen responds differently from the three.js example page (http://threejs.org/examples/#misc_controls_orbit), while leaving the scene causes the spin to stop, returning (if you're still holding down the mouse button) resumes the spin. On the example page, (using the same code, so it must be something codepen specific) spinning does not resume.
Thought that maybe if I attached the event listener to the window or document instead of the dom element it might help, but no dice.
Changed OrbitControls.js lines 893 - 901 from:
scope.domElement.addEventListener( 'contextmenu', onContextMenu, false );
scope.domElement.addEventListener( 'mousedown', onMouseDown, false );
scope.domElement.addEventListener( 'mousewheel', onMouseWheel, false );
scope.domElement.addEventListener( 'MozMousePixelScroll', onMouseWheel, false ); // firefox
scope.domElement.addEventListener( 'touchstart', onTouchStart, false );
scope.domElement.addEventListener( 'touchend', onTouchEnd, false );
scope.domElement.addEventListener( 'touchmove', onTouchMove, false );
to:
window.addEventListener( 'contextmenu', onContextMenu, false );
window.addEventListener( 'mousedown', onMouseDown, false );
window.addEventListener( 'mousewheel', onMouseWheel, false );
window.addEventListener( 'MozMousePixelScroll', onMouseWheel, false ); // firefox
window.addEventListener( 'touchstart', onTouchStart, false );
window.addEventListener( 'touchend', onTouchEnd, false );
window.addEventListener( 'touchmove', onTouchMove, false );
window.addEventListener( 'keydown', onKeyDown, false );
Upvotes: 2
Views: 1176
Reputation: 2853
What you want is line 703 in orbitControls.js (r.76), comment out the mouseout declaration, leave the others. This issue has come up many times. Maybe it ought to be defaulted to commented out or available as an option in orbit control's constructor parameters. Simple to code for a pull request.
Upvotes: 1