Simulate graph states in the browser
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

orbitcontrols.js 7.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. // three.js - http://github.com/mrdoob/three.js
  2. /**
  3. * @author qiao / https://github.com/qiao
  4. * @author mrdoob / http://mrdoob.com
  5. * @author alteredq / http://alteredqualia.com/
  6. * @author WestLangley / http://github.com/WestLangley
  7. */
  8. THREE.OrbitControls = function ( object, domElement ) {
  9. this.object = object;
  10. this.domElement = ( domElement !== undefined ) ? domElement : document;
  11. // API
  12. this.enabled = true;
  13. this.center = new THREE.Vector3();
  14. this.target = new THREE.Vector3();
  15. this.userZoom = true;
  16. this.userZoomSpeed = 1.0;
  17. this.userRotate = true;
  18. this.userRotateSpeed = 1.0;
  19. this.userPan = true;
  20. this.userPanSpeed = 0.1;
  21. this.autoRotate = false;
  22. this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
  23. this.minPolarAngle = 0; // radians
  24. this.maxPolarAngle = Math.PI; // radians
  25. this.minDistance = 0;
  26. this.maxDistance = Infinity;
  27. // 65 /*A*/, 83 /*S*/, 68 /*D*/
  28. this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40, ROTATE: 65, ZOOM: 83, PAN: 68 };
  29. // internals
  30. var scope = this;
  31. var EPS = 0.000001;
  32. var PIXELS_PER_ROUND = 1800;
  33. var rotateStart = new THREE.Vector2();
  34. var rotateEnd = new THREE.Vector2();
  35. var rotateDelta = new THREE.Vector2();
  36. var zoomStart = new THREE.Vector2();
  37. var zoomEnd = new THREE.Vector2();
  38. var zoomDelta = new THREE.Vector2();
  39. var phiDelta = 0;
  40. var thetaDelta = 0;
  41. var scale = 1;
  42. var lastPosition = new THREE.Vector3();
  43. var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2 };
  44. var state = STATE.NONE;
  45. // events
  46. var changeEvent = { type: 'change' };
  47. this.rotateLeft = function ( angle ) {
  48. if ( angle === undefined ) {
  49. angle = getAutoRotationAngle();
  50. }
  51. thetaDelta -= angle;
  52. };
  53. this.rotateRight = function ( angle ) {
  54. if ( angle === undefined ) {
  55. angle = getAutoRotationAngle();
  56. }
  57. thetaDelta += angle;
  58. };
  59. this.rotateUp = function ( angle ) {
  60. if ( angle === undefined ) {
  61. angle = getAutoRotationAngle();
  62. }
  63. phiDelta -= angle;
  64. };
  65. this.rotateDown = function ( angle ) {
  66. if ( angle === undefined ) {
  67. angle = getAutoRotationAngle();
  68. }
  69. phiDelta += angle;
  70. };
  71. this.zoomIn = function ( zoomScale ) {
  72. if ( zoomScale === undefined ) {
  73. zoomScale = getZoomScale();
  74. }
  75. scale /= zoomScale;
  76. };
  77. this.zoomOut = function ( zoomScale ) {
  78. if ( zoomScale === undefined ) {
  79. zoomScale = getZoomScale();
  80. }
  81. scale *= zoomScale;
  82. };
  83. this.pan = function ( distance ) {
  84. distance.transformDirection( this.object.matrix );
  85. distance.multiplyScalar( scope.userPanSpeed );
  86. this.object.position.add( distance );
  87. this.center.add( distance );
  88. this.target.add( distance );
  89. };
  90. this.update = function () {
  91. var position = this.object.position;
  92. var offset = position.clone().sub( this.center );
  93. var diff = this.center.clone().sub( this.target ).multiplyScalar(0.2);
  94. this.center.sub(diff);
  95. // angle from z-axis around y-axis
  96. var theta = Math.atan2( offset.x, offset.z );
  97. // angle from y-axis
  98. var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y );
  99. if ( this.autoRotate ) {
  100. this.rotateLeft( getAutoRotationAngle() );
  101. }
  102. theta += thetaDelta;
  103. phi += phiDelta;
  104. // restrict phi to be between desired limits
  105. phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) );
  106. // restrict phi to be betwee EPS and PI-EPS
  107. phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );
  108. var radius = offset.length() * scale;
  109. // restrict radius to be between desired limits
  110. radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) );
  111. offset.x = radius * Math.sin( phi ) * Math.sin( theta );
  112. offset.y = radius * Math.cos( phi );
  113. offset.z = radius * Math.sin( phi ) * Math.cos( theta );
  114. position.copy( this.center ).add( offset );
  115. this.object.lookAt( this.center );
  116. thetaDelta /= 1.5;
  117. phiDelta /= 1.5;
  118. scale = 1;
  119. if ( lastPosition.distanceTo( this.object.position ) > 0.01 ) {
  120. this.dispatchEvent( changeEvent );
  121. lastPosition.copy( this.object.position );
  122. }
  123. };
  124. function getAutoRotationAngle() {
  125. return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
  126. }
  127. function getZoomScale() {
  128. return Math.pow( 0.95, scope.userZoomSpeed );
  129. }
  130. function onMouseDown( event ) {
  131. if ( scope.enabled === false ) return;
  132. if ( scope.userRotate === false ) return;
  133. event.preventDefault();
  134. if ( state === STATE.NONE )
  135. {
  136. if ( event.button === 0 )
  137. state = STATE.ROTATE;
  138. if ( event.button === 1 )
  139. state = STATE.ZOOM;
  140. if ( event.button === 2 )
  141. state = STATE.PAN;
  142. }
  143. if ( state === STATE.ROTATE ) {
  144. //state = STATE.ROTATE;
  145. rotateStart.set( event.clientX, event.clientY );
  146. } else if ( state === STATE.ZOOM ) {
  147. //state = STATE.ZOOM;
  148. zoomStart.set( event.clientX, event.clientY );
  149. } else if ( state === STATE.PAN ) {
  150. //state = STATE.PAN;
  151. }
  152. document.addEventListener( 'mousemove', onMouseMove, false );
  153. document.addEventListener( 'mouseup', onMouseUp, false );
  154. }
  155. function onMouseMove( event ) {
  156. if ( scope.enabled === false ) return;
  157. event.preventDefault();
  158. if ( state === STATE.ROTATE ) {
  159. rotateEnd.set( event.clientX, event.clientY );
  160. rotateDelta.subVectors( rotateEnd, rotateStart );
  161. scope.rotateLeft( 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed );
  162. scope.rotateUp( 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed );
  163. rotateStart.copy( rotateEnd );
  164. } else if ( state === STATE.ZOOM ) {
  165. zoomEnd.set( event.clientX, event.clientY );
  166. zoomDelta.subVectors( zoomEnd, zoomStart );
  167. if ( zoomDelta.y > 0 ) {
  168. scope.zoomIn();
  169. } else {
  170. scope.zoomOut();
  171. }
  172. zoomStart.copy( zoomEnd );
  173. } else if ( state === STATE.PAN ) {
  174. var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
  175. var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;
  176. scope.pan( new THREE.Vector3( - movementX, movementY, 0 ) );
  177. }
  178. }
  179. function onMouseUp( event ) {
  180. if ( scope.enabled === false ) return;
  181. if ( scope.userRotate === false ) return;
  182. document.removeEventListener( 'mousemove', onMouseMove, false );
  183. document.removeEventListener( 'mouseup', onMouseUp, false );
  184. state = STATE.NONE;
  185. }
  186. function onMouseWheel( event ) {
  187. if ( scope.enabled === false ) return;
  188. if ( scope.userZoom === false ) return;
  189. var delta = 0;
  190. if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9
  191. delta = event.wheelDelta;
  192. } else if ( event.detail ) { // Firefox
  193. delta = - event.detail;
  194. }
  195. if ( delta > 0 ) {
  196. scope.zoomOut();
  197. } else {
  198. scope.zoomIn();
  199. }
  200. }
  201. function onKeyDown( event ) {
  202. if ( scope.enabled === false ) return;
  203. if ( scope.userPan === false ) return;
  204. switch ( event.keyCode ) {
  205. /*case scope.keys.UP:
  206. scope.pan( new THREE.Vector3( 0, 1, 0 ) );
  207. break;
  208. case scope.keys.BOTTOM:
  209. scope.pan( new THREE.Vector3( 0, - 1, 0 ) );
  210. break;
  211. case scope.keys.LEFT:
  212. scope.pan( new THREE.Vector3( - 1, 0, 0 ) );
  213. break;
  214. case scope.keys.RIGHT:
  215. scope.pan( new THREE.Vector3( 1, 0, 0 ) );
  216. break;
  217. */
  218. case scope.keys.ROTATE:
  219. state = STATE.ROTATE;
  220. break;
  221. case scope.keys.ZOOM:
  222. state = STATE.ZOOM;
  223. break;
  224. case scope.keys.PAN:
  225. state = STATE.PAN;
  226. break;
  227. }
  228. }
  229. function onKeyUp( event ) {
  230. switch ( event.keyCode ) {
  231. case scope.keys.ROTATE:
  232. case scope.keys.ZOOM:
  233. case scope.keys.PAN:
  234. state = STATE.NONE;
  235. break;
  236. }
  237. }
  238. this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
  239. this.domElement.addEventListener( 'mousedown', onMouseDown, false );
  240. this.domElement.addEventListener( 'mousewheel', onMouseWheel, false );
  241. this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox
  242. window.addEventListener( 'keydown', onKeyDown, false );
  243. window.addEventListener( 'keyup', onKeyUp, false );
  244. };
  245. THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );