title: How to control the data.gui.js that do not affect the object(Three.js r66)
body: <p>I write a trackball to control the object rotation, everything goes fine. However, when I add the gui component to the program, and when I put the mouse to change the gui, the object is moving. Because my trackball project the screen coordinate to the virtual ball, when my mouse is on the gui component, it is still in the screen, and it makes the object  move. How to avoid that? I try t find the reason about the trackball three.js has, and do not find the a result. Why his trackball do not affact the gui object?</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html lang="en"&gt;
  &lt;head&gt;
      &lt;title&gt;three.js canvas - geometry - cube&lt;/title&gt;
      &lt;meta charset="utf-8"&gt;
      &lt;meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"&gt;
      &lt;style&gt;
          body {
              font-family: Monospace;
              background-color: #f0f0f0;
              margin: 0px;
              overflow: hidden;
          }
      &lt;/style&gt;
  &lt;/head&gt;
  &lt;body&gt;
  
  &lt;script src="../build/three.min.js"&gt;&lt;/script&gt;
  
  &lt;script src="js/libs/dat.gui.min.js"&gt;&lt;/script&gt;
  &lt;script src="js/libs/stats.min.js"&gt;&lt;/script&gt;
  &lt;script&gt;
  
  var container, stats;
  
  var camera, scene, renderer;
  
  var cube, plane;
  
  
  
  var mouseDown = false;
  var rotateStartP = new THREE.Vector3(0,0,1);
  var rotateEndP = new THREE.Vector3(0,0,1);
  
  var lastPosX;
  var lastPosY;
  var targetRotationY = 0;
  var targetRotationX = 0;
  var quater;
  //var rotateQuaternion = new THREE.Quaternion();
  var windowHalfX = window.innerWidth / 2;
  var windowHalfY = window.innerHeight / 2;
  
  init();
  animate();
  
  function init() {
  
      container = document.createElement( 'div' );
      document.body.appendChild( container );
  
      var info = document.createElement( 'div' );
      info.style.position = 'absolute';
      info.style.top = '10px';
      info.style.width = '100%';
      info.style.textAlign = 'center';
      info.innerHTML = 'Drag to spin the cube';
      container.appendChild( info );
  
      camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
      camera.position.y = 150;
      camera.position.z = 500;
  
      scene = new THREE.Scene();
  
      // Cube
  
      var geometry = new THREE.CubeGeometry( 200, 200, 200 );
  
      for ( var i = 0; i &lt; geometry.faces.length; i += 2 ) {
  
          var hex = Math.random() * 0xffffff;
          geometry.faces[ i ].color.setHex( hex );
          geometry.faces[ i + 1 ].color.setHex( hex );
  
      }
  
      var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors, overdraw: 0.5 } );
  
      cube = new THREE.Mesh( geometry, material );
      cube.position.y = 150;
      scene.add( cube );
  
      // Plane
  
      var geometry = new THREE.PlaneGeometry( 200, 200 );
      geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
  
      var material = new THREE.MeshBasicMaterial( { color: 0xe0e0e0, overdraw: 0.5 } );
  
      plane = new THREE.Mesh( geometry, material );
      scene.add( plane );
  
      renderer = new THREE.CanvasRenderer();
      renderer.setClearColor( 0xf0f0f0 );
      renderer.setSize( window.innerWidth, window.innerHeight );
  
      container.appendChild( renderer.domElement );
      //GUI
      var controls = new function () {
  
          this.xx = false;
          this.yy = 512;
  
  
  
          this.onChange = function () {
  
          }
  
      };
  
      var gui = new dat.GUI();
      gui.add(controls, 'xx').onChange(controls.onChange);
      gui.add(controls, 'yy', 1, 10).step(1).onChange(controls.onChange);
  
      stats = new Stats();
      stats.domElement.style.position = 'absolute';
      stats.domElement.style.top = '0px';
      container.appendChild( stats.domElement );
  
      document.addEventListener( 'mousedown', onDocumentMouseDown, false );
      document.addEventListener( 'touchstart', onDocumentTouchStart, false );
      document.addEventListener( 'touchmove', onDocumentTouchMove, false );
  
      //
  
      window.addEventListener( 'resize', onWindowResize, false );
  
  }
  
  function onWindowResize() {
  
      windowHalfX = window.innerWidth / 2;
      windowHalfY = window.innerHeight / 2;
  
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
  
      renderer.setSize( window.innerWidth, window.innerHeight );
  
  }
  
  //
  
  function onDocumentMouseDown( event ) {
  
      event.preventDefault();
  
      document.addEventListener( 'mousemove', onDocumentMouseMove, false );
      document.addEventListener( 'mouseup', onDocumentMouseUp, false );
      document.addEventListener( 'mouseout', onDocumentMouseOut, false );
      mouseDown = true;
      rotateStartP = projectOnTrackball(event.clientX, event.clientY);
  }
  
  function onDocumentMouseMove( event ) {
  
      if(!mouseDown)
      {
          return;
      }
  
      rotateEndP = projectOnTrackball(event.clientX, event.clientY);
  
  
  }
  function getMouseOnScreen( pageX, pageY) {
  
      return new THREE.Vector2.set(pageX / window.innerWidth ,pageY / window.innerHeight);
  
  }
  
  function projectOnTrackball(pageX, pageY) // The screen coordinate[(0,0)on the left-top] convert to the
      //trackball coordinate [(0,0) on the center of the page]
  {
      var mouseOnBall = new THREE.Vector3();
      mouseOnBall.set(
                      ( pageX - window.innerWidth * 0.5 ) / (window.innerWidth * .5),
                      ( window.innerHeight * 0.5 - pageY ) / ( window.innerHeight * .5),
              0.0
      );
  
      var length = mouseOnBall.length();
      if (length &gt; 1.0) {
  
          mouseOnBall.normalize();
  
      }
      else {
          mouseOnBall.z = Math.sqrt(1.0 - length * length);
      }
      return mouseOnBall;
  }
  
  function rotateMatrix(rotateStart, rotateEnd)
  {
      var axis = new THREE.Vector3(),
              quaternion = new THREE.Quaternion();
  
      var angle = Math.acos( rotateStart.dot( rotateEnd ) / rotateStart.length() / rotateEnd.length() );
  
      if ( angle )
      {
          axis.crossVectors( rotateStart, rotateEnd ).normalize();
          angle *= 0.01;            //Here we could define rotate speed
          quaternion.setFromAxisAngle( axis, angle );
      }
      return  quaternion;
  }
  
  function onDocumentMouseUp( event ) {
  
      document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
      document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
      document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
      mouseDown = false;
      rotateStartP = rotateEndP;
  
  }
  
  function onDocumentMouseOut( event ) {
  
      document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
      document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
      document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
  
  }
  
  function onDocumentTouchStart( event ) {
  
      if ( event.touches.length === 1 ) {
  
          event.preventDefault();
          /*
           mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
           targetRotationOnMouseDownX = targetRotationX;
           mouseYOnMouseDown = event.touches[ 0 ].pageY - windowHalfY;
           targetRotationOnMouseDownY = targetRotationY;  */
      }
  
  }
  
  function onDocumentTouchMove( event ) {
  
      if ( event.touches.length === 1 ) {
  
          event.preventDefault();
          /*
           mouseX = event.touches[ 0 ].pageX - windowHalfX;
           targetRotationX = targetRotationOnMouseDownX + ( mouseX - mouseXOnMouseDown ) * 0.05;
           mouseY = event.touches[ 0 ].pageY - windowHalfY;
           targetRotationY = targetRotationOnMouseDownY + ( mouseY - mouseYOnMouseDown ) * 0.05; */
      }
  
  }
  
  //
  function animate() {
  
      requestAnimationFrame( animate );
      render();
      stats.update();
  
  }
  
  function render() {
      //if(rotateStartP != rotateEndP) {
      //rotateQuaternion = rotateMatrix(rotateStartP, rotateEndP);
      //quater=cube.quaternion;
      //quater.multiplyQuaternions(rotateQuaternion, quater);
      //quater.multiply(rotateQuaternion);
      //quater.normalize();
      var rotateQuaternion = rotateMatrix(rotateStartP, rotateEndP);
      quater=cube.quaternion;
      quater.multiplyQuaternions(rotateQuaternion,quater);
      quater.normalize();
      cube.setRotationFromQuaternion(quater);
      // }
  
  
      renderer.render( scene, camera );
  
  }
  
  &lt;/script&gt;
  
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <h2>Change my code to ObjectTrackball.js</h2>
  
  <p>The code is as follows:</p>
  
  <pre><code>TrackballControls = function ( object, domElement ) {
  
      var _this = this;
  
      _this.quater = object.quaternion;
      _this.object = object;
      _this.domElement = ( domElement !== undefined ) ? domElement : document;
  
      _this.zoomValue = 0;
      _this.mouseDown = true;
  
      _this.rotateStartP = new THREE.Vector3();
      _this.rotateEndP = new THREE.Vector3();
  
      // events
      var changeEvent = { type: 'change' };
  
      // methods
  
      this.handleEvent = function ( event ) {
  
          if ( typeof this[ event.type ] == 'function' ) {
  
              this[ event.type ]( event );
  
          }
  
      };
  
      this.update = function () {
  
          var rotateQuaternion = rotateMatrix(_this.rotateStartP, _this.rotateEndP);
          _this.quater = _this.object.quaternion;
          _this.quater.multiplyQuaternions(rotateQuaternion,_this.quater);
          _this.quater.normalize();
          _this.object.setRotationFromQuaternion(_this.quater);
          _this.object.position.z += _this.zoomValue;
          _this.zoomValue = 0;
  
      };
  
  
  
      function mousedown( event ) {
  
          event.preventDefault();
          _this.mouseDown = true;
          _this.rotateStartP = projectOnTrackball(event.clientX, event.clientY);
  
          document.addEventListener( 'mousemove', mousemove, false );
          document.addEventListener( 'mouseup', mouseup, false );
  
  
  
      }
      function getMouseOnScreen( pageX, pageY) {
  
          return new THREE.Vector2.set(pageX / window.innerWidth ,pageY / window.innerHeight);
  
      }
  
      function projectOnTrackball(pageX, pageY) // The screen coordinate[(0,0)on the left-top] convert to the
          //trackball coordinate [(0,0) on the center of the page]
      {
          var mouseOnBall = new THREE.Vector3();
          mouseOnBall.set(
                  ( pageX - window.innerWidth * 0.5 ) / (window.innerWidth * .5),
                  ( window.innerHeight * 0.5 - pageY ) / ( window.innerHeight * .5),
              0.0
          );
  
          var length = mouseOnBall.length();
          if (length &gt; 1.0) {
  
              mouseOnBall.normalize();
  
          }
          else {
              mouseOnBall.z = Math.sqrt(1.0 - length * length);
          }
          return mouseOnBall;
      }
  
      function rotateMatrix(rotateStart, rotateEnd)
      {
          var axis = new THREE.Vector3(),
              quaternion = new THREE.Quaternion();
  
          var angle = Math.acos( rotateStart.dot( rotateEnd ) / rotateStart.length() / rotateEnd.length() );
  
          if ( angle )
          {
              axis.crossVectors( rotateStart, rotateEnd ).normalize();
              angle *= 0.01;            //Here we could define rotate speed
              quaternion.setFromAxisAngle( axis, angle );
          }
          return  quaternion;
      }
  
      function mousemove( event ) {
  
          if(!_this.mouseDown)
          {
              return;
          }
  
          _this.rotateEndP = projectOnTrackball(event.clientX, event.clientY);
  
      }
  
      function mouseup( event ) {
  
          _this.mouseDown = false;
          _this.rotateStartP = _this.rotateEndP;
          document.removeEventListener( 'mousemove', mousemove );
          document.removeEventListener( 'mouseup', mouseup );
  
      }
  
      function mousewheel( event ) {
  
          event.preventDefault();
          event.stopPropagation();
  
          var delta = 0;
  
          if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9
  
              delta = event.wheelDelta / 40;
  
          } else if ( event.detail ) { // Firefox
  
              delta = - event.detail / 3;
  
          }
  
          _this.zoomValue += delta;
  
      }
  
      this.domElement.addEventListener( 'mousedown', mousedown, false );
  
      this.domElement.addEventListener( 'mousewheel', mousewheel, false );
      this.domElement.addEventListener( 'DOMMouseScroll', mousewheel, false ); // firefox
  
  };
  
  TrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype );
  </code></pre>
  
  <h2>Code of The Object control application (Three.js r66)</h2>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html lang="en"&gt;
  &lt;head&gt;
      &lt;title&gt;three.js canvas - geometry - cube&lt;/title&gt;
      &lt;meta charset="utf-8"&gt;
      &lt;meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"&gt;
      &lt;style&gt;
          body {
              font-family: Monospace;
              background-color: #f0f0f0;
              margin: 0px;
              overflow: hidden;
          }
      &lt;/style&gt;
  &lt;/head&gt;
  &lt;body&gt;
  
  &lt;script src="../build/three.min.js"&gt;&lt;/script&gt;
  
  &lt;script src="js/libs/dat.gui.min.js"&gt;&lt;/script&gt;
  &lt;script src="js/libs/stats.min.js"&gt;&lt;/script&gt;
  &lt;script src="js/controls/ObjectTrackballControl.js"&gt;&lt;/script&gt;
  &lt;script&gt;
  
  var container, stats;
  
  var camera, scene, renderer;
  
  var cube, plane;
  var control;
  
  
  var mouseDown = false;
  var rotateStartP = new THREE.Vector3(0,0,1);
  var rotateEndP = new THREE.Vector3(0,0,1);
  
  var lastPosX;
  var lastPosY;
  var targetRotationY = 0;
  var targetRotationX = 0;
  var quater;
  //var rotateQuaternion = new THREE.Quaternion();
  var windowHalfX = window.innerWidth / 2;
  var windowHalfY = window.innerHeight / 2;
  
  init();
  animate();
  
  function init() {
  
      container = document.createElement( 'div' );
      document.body.appendChild( container );
  
      var info = document.createElement( 'div' );
      info.style.position = 'absolute';
      info.style.top = '10px';
      info.style.width = '100%';
      info.style.textAlign = 'center';
      info.innerHTML = 'Drag to spin the cube';
      container.appendChild( info );
  
      camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
      camera.position.y = 150;
      camera.position.z = 500;
  
      scene = new THREE.Scene();
  
      // Cube
  
      var geometry = new THREE.CubeGeometry( 200, 200, 200 );
  
      for ( var i = 0; i &lt; geometry.faces.length; i += 2 ) {
  
          var hex = Math.random() * 0xffffff;
          geometry.faces[ i ].color.setHex( hex );
          geometry.faces[ i + 1 ].color.setHex( hex );
  
      }
  
      var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors, overdraw: 0.5 } );
  
      cube = new THREE.Mesh( geometry, material );
      cube.position.y = 150;
      scene.add( cube );
  
      control = new TrackballControls(cube);
      // Plane
  
      var geometry = new THREE.PlaneGeometry( 200, 200 );
      geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
  
      var material = new THREE.MeshBasicMaterial( { color: 0xe0e0e0, overdraw: 0.5 } );
  
      plane = new THREE.Mesh( geometry, material );
      scene.add( plane );
  
      renderer = new THREE.CanvasRenderer();
      renderer.setClearColor( 0xf0f0f0 );
      renderer.setSize( window.innerWidth, window.innerHeight );
  
      container.appendChild( renderer.domElement );
      //GUI
      var controls = new function () {
  
          this.xx = false;
          this.yy = 512;
  
  
  
          this.onChange = function () {
  
          }
  
      };
  
      var gui = new dat.GUI();
      gui.add(controls, 'xx').onChange(controls.onChange);
      gui.add(controls, 'yy', 1, 10).step(1).onChange(controls.onChange);
  
      stats = new Stats();
      stats.domElement.style.position = 'absolute';
      stats.domElement.style.top = '0px';
      container.appendChild( stats.domElement );
  
      //
  
      window.addEventListener( 'resize', onWindowResize, false );
  
  }
  
  function onWindowResize() {
  
      windowHalfX = window.innerWidth / 2;
      windowHalfY = window.innerHeight / 2;
  
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
  
      renderer.setSize( window.innerWidth, window.innerHeight );
  
  }
  
  
  //
  function animate() {
  
      requestAnimationFrame( animate );
      render();
      stats.update();
  
  }
  
  function render() {
  
      control.update();
      renderer.render( scene, camera );
  
  }
  
  &lt;/script&gt;
  
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>