How to enhance mouse tracking beyond browser window boundaries in Three.js and across various page elements

I'm facing an issue with my three.js scene where I have buttons positioned on top and off to the side of the scene. When you click and drag to spin the camera, the spinning stops when dragging over the buttons or outside the window. I am using three.js R76 and OrbitControls.js. Is there a simple way to make the scene continue listening to mouse movement even when a button is clicked?

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(); 

            render();

        }

        function render() {

            renderer.render( scene, camera );

        }

The spinning of the camera stops when the mouse goes out of the scene but I want it to keep rotating. On the codepen page, the behavior is different compared to the official three.js example (). The spinning does not resume on the codepen page once it stops.

I tried attaching event listeners to the window instead of the dom element based on OrbitControls.js lines 893 - 901:

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 );

Answer №1

The solution you're looking for can be found on line 703 of orbitControls.js (r.76). Simply comment out the mouseout declaration and leave the others intact. This issue has been raised multiple times in the past. Perhaps it should be set to commented out by default or included as an option in the orbit control's constructor parameters. Implementing this change would be straightforward for a pull request to be made.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Retrieving data from Firebase query and displaying as an array of results

Currently utilizing the @react-native-firebase wrapper for interaction with Firebase's Firestore. Within my function, some querying to a specific collection is performed, with the expected result being an Array object containing each located document. ...

Iterate over each item in the select and include a blank option if either of the elements is missing

Having trouble with 2 drop down menus, select1 and select2. I select item1 from select1 and then click the OK button. But when the selected index is 0 (first option), I want to loop through the items of both drop downs. If the elements at the same index ( ...

What strategies can be implemented to improve the total blocking time in Vue for optimal performance

I'm facing a challenge that I can't seem to resolve. My page has a high total blocking time (2+ sec). Despite trying to load every vue component asynchronously, the issue persists with 2+ sec TBT. I'm puzzled by what could be causing such a ...

A guide on simulating an emit event while testing a Vue child component using Jest

During my testing of multiple child components, I have encountered a frustrating issue that seems to be poor practice. Each time I trigger an emit in a child component, it prompts me to import the parent component and subsequently set up all other child co ...

Retrieving JSON data from a URL with PHP

Attempting to retrieve JSON data from the following URL: $search_data&format=json&nojsoncallback=1 The information I am aiming to obtain based on the above link is as follows: { "places": { "place": [ { ...

When it comes to assigning a background to a div using jQuery and JSON

I have been experimenting with creating a database using only JSON and surprisingly, it worked once I added a "js/" in the URL. However, my current issue lies with CSS. Let me elaborate. Here is the JSON data: [ { "title":"Facebook", ...

Interactive pop-up messages created with CSS and JavaScript that appear and fade based on the URL query string

I have a referral form on this page that I want people to use repeatedly. After submitting the form, it reloads the page with the query string ?referralsent=true so users can refer more people through the form. However, I also want to show users a confir ...

What is the best way to obtain a direct file link from a server URL using JavaScript?

After acquiring a file located at /home/johndoe/index.html, I am utilizing a tool like XAMPP to host, with the folder /home being hosted on localhost. The variables in play are as follows: $server_addr = "localhost"; $server_root = "/home"; $file_dir = " ...

steps to iterate through an array or object in javascript

Hello, I am facing an issue while trying to loop through an array or object. Can someone help me out? Are arrays and objects different when it comes to using foreach? function fetchData() { fetch("https://covid-193.p.rapidapi.com/statistics", { ...

Vue and Jexcel: maximizing efficiency with event handling and dynamic calculations

I am trying to utilize the vue wrapper for jexcel and want to trigger the undo function from the toolbar computed field. However, I am facing difficulties accessing the spreadsheet instance as it throws an error saying 'this.undo is undefined.' ...

Tips for accessing hidden field values in a second jsp page

I have a webpage called page1.jsp where I am including hidden fields. Here is the code snippet: <form action = "page2.jsp" method = "post" id = "hiddenValuesForm"> <input type = "hidden" name = "userData" value="" id = "useDataID"> <input t ...

What is the approach of Angular 2 in managing attributes formatted in camelCase?

Recently, I've been dedicating my time to a personal project centered around web components. In this endeavor, I have been exploring the development of my own data binding library. Progress has been made in creating key functionalities akin to those f ...

Is it possible to modify the appearance or behavior of a button in a React application based on its current state?

I'm looking to customize the color of a button based on different states. For example, if the state is active, the button should appear in red; otherwise it should be blue. Can anyone suggest how this can be achieved in React? Furthermore, I would als ...

Spinning a line in three.js along the circumference of a circle

let lineGeo = new THREE.Geometry(); let lineMat = new THREE.LineBasicMaterial({ color: 0x000000 }); lineGeo.vertices.push( new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 10, 0), ); let myLine = new THREE.Line(lineGeo, lineMat); scene.add(myLi ...

Post-render for HTML linkage

Is there a method to execute customized code after Knockout has inserted the html into the DOM and completed rendering? This is required in order to bind a nested view model to dynamically generated html code. Perhaps like this: <div data-bind="html: ...

"Utilizing Express's Jade middleware to efficiently handle and manage

Can you create a custom exception handler for errors in jade templates? For example: // server.js app = express(); app.set('view engine', jade); app.locals.js = function () { throw new Error('hello'); } // views/index.jade html != ...

Fill the rows of the <Table> using HTML code

I am encountering an issue with displaying data in a table on a screen: <table id="TransactionTable" class="table table-responsive table-striped"> <thead> <tr> <th></th> <th>Date</ ...

Creating a Vue.js component that animates text to fade in and out within a textarea when a button

I need assistance with updating a <textarea> element in my Vue application. Currently, I have the textarea bound to some data in my state. However, when a button is clicked, I want the existing data in the textarea to fade out and be replaced with ne ...

There is an array present with data filled in, but unfortunately, I am unable to retrieve specific elements

As I work on my WordPress 4.7.2 website, I find myself making an AJAX call. The PHP function handling this call returns an array using wp_json_encode(). When I view the data array in the success callback of the AJAX function, everything looks just as expec ...

Setting form values using Angular 9

I am currently facing a challenge that I could use some assistance with. My dilemma involves integrating a new payment system, and I seem to be encountering some obstacles. Here is a snippet of what I have: options: PaystackOptions= { amount: 5000, emai ...