君子性非异也,善假于物也 - Threejs 引入TrackballControls 查看场景
君子性非异也,善假于物也 - Threejs 引入TrackballControls 查看场景
太阳火神的美丽人生 (http://blog.csdn.net/opengl_es)
本文遵循“署名-非商业用途-保持一致”创作公用协议
转载请保留此句:太阳火神的美丽人生 - 本博客专注于 敏捷开发及移动和物联设备研究:iOS、Android、Html5、Arduino、pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作。
以下为 html 源文件中引入 TrackballControls 库的关键代码,其中 camera 和 renderer 需要对 Threejs 有所了解方可理解:
以下代码归原作者所有,但在以下所署两网址未找到与此一致的最新代码,而有一些类似的可用代码,可以参考一下。
上面代码中引用的 js/controls/TrackballControls.js 代码原文,可拷贝可新建 TrackballControls.js 引入,并按上面方式使用即可:
/*** @author Eberhard Graether / http://egraether.com/* @author Mark Lundin / http://mark-lundin.com*/THREE.TrackballControls = function ( object, domElement ) {var _this = this;var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };this.object = object;this.domElement = ( domElement !== undefined ) ? domElement : document;// APIthis.enabled = true;this.screen = { left: 0, top: 0, width: 0, height: 0 };this.rotateSpeed = 1.0;this.zoomSpeed = 1.2;this.panSpeed = 0.3;this.noRotate = false;this.noZoom = false;this.noPan = false;this.noRoll = false;this.staticMoving = false;this.dynamicDampingFactor = 0.2;this.minDistance = 0;this.maxDistance = Infinity;this.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ];// internalsthis.target = new THREE.Vector3();var EPS = 0.000001;var lastPosition = new THREE.Vector3();var _state = STATE.NONE,_prevState = STATE.NONE,_eye = new THREE.Vector3(),_rotateStart = new THREE.Vector3(),_rotateEnd = new THREE.Vector3(),_zoomStart = new THREE.Vector2(),_zoomEnd = new THREE.Vector2(),_touchZoomDistanceStart = 0,_touchZoomDistanceEnd = 0,_panStart = new THREE.Vector2(),_panEnd = new THREE.Vector2();// for resetthis.target0 = this.target.clone();this.position0 = this.object.position.clone();this.up0 = this.object.up.clone();// eventsvar changeEvent = { type: 'change' };var startEvent = { type: 'start'};var endEvent = { type: 'end'};// methodsthis.handleResize = function () {if ( this.domElement === document ) {this.screen.left = 0;this.screen.top = 0;this.screen.width = window.innerWidth;this.screen.height = window.innerHeight;} else {var box = this.domElement.getBoundingClientRect();// adjustments come from similar code in the jquery offset() functionvar d = this.domElement.ownerDocument.documentElement;this.screen.left = box.left + window.pageXOffset - d.clientLeft;this.screen.top = box.top + window.pageYOffset - d.clientTop;this.screen.width = box.width;this.screen.height = box.height;}};this.handleEvent = function ( event ) {if ( typeof this[ event.type ] == 'function' ) {this[ event.type ]( event );}};var getMouseOnScreen = ( function () {var vector = new THREE.Vector2();return function ( pageX, pageY ) {vector.set(( pageX - _this.screen.left ) / _this.screen.width,( pageY - _this.screen.top ) / _this.screen.height);return vector;};}() );var getMouseProjectionOnBall = ( function () {var vector = new THREE.Vector3();var objectUp = new THREE.Vector3();var mouseOnBall = new THREE.Vector3();return function ( pageX, pageY ) {mouseOnBall.set(( pageX - _this.screen.width * 0.5 - _this.screen.left ) / (_this.screen.width*.5),( _this.screen.height * 0.5 + _this.screen.top - pageY ) / (_this.screen.height*.5),0.0);var length = mouseOnBall.length();if ( _this.noRoll ) {if ( length < Math.SQRT1_2 ) {mouseOnBall.z = Math.sqrt( 1.0 - length*length );} else {mouseOnBall.z = .5 / length;}} else if ( length > 1.0 ) {mouseOnBall.normalize();} else {mouseOnBall.z = Math.sqrt( 1.0 - length * length );}_eye.copy( _this.object.position ).sub( _this.target );vector.copy( _this.object.up ).setLength( mouseOnBall.y )vector.add( objectUp.copy( _this.object.up ).cross( _eye ).setLength( mouseOnBall.x ) );vector.add( _eye.setLength( mouseOnBall.z ) );return vector;};}() );this.rotateCamera = (function(){var axis = new THREE.Vector3(),quaternion = new THREE.Quaternion();return function () {var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() );if ( angle ) {axis.crossVectors( _rotateStart, _rotateEnd ).normalize();angle *= _this.rotateSpeed;quaternion.setFromAxisAngle( axis, -angle );_eye.applyQuaternion( quaternion );_this.object.up.applyQuaternion( quaternion );_rotateEnd.applyQuaternion( quaternion );if ( _this.staticMoving ) {_rotateStart.copy( _rotateEnd );} else {quaternion.setFromAxisAngle( axis, angle * ( _this.dynamicDampingFactor - 1.0 ) );_rotateStart.applyQuaternion( quaternion );}}}}());this.zoomCamera = function () {if ( _state === STATE.TOUCH_ZOOM_PAN ) {var factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;_touchZoomDistanceStart = _touchZoomDistanceEnd;_eye.multiplyScalar( factor );} else {var factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed;if ( factor !== 1.0 && factor > 0.0 ) {_eye.multiplyScalar( factor );if ( _this.staticMoving ) {_zoomStart.copy( _zoomEnd );} else {_zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;}}}};this.panCamera = (function(){var mouseChange = new THREE.Vector2(),objectUp = new THREE.Vector3(),pan = new THREE.Vector3();return function () {mouseChange.copy( _panEnd ).sub( _panStart );if ( mouseChange.lengthSq() ) {mouseChange.multiplyScalar( _eye.length() * _this.panSpeed );pan.copy( _eye ).cross( _this.object.up ).setLength( mouseChange.x );pan.add( objectUp.copy( _this.object.up ).setLength( mouseChange.y ) );_this.object.position.add( pan );_this.target.add( pan );if ( _this.staticMoving ) {_panStart.copy( _panEnd );} else {_panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) );}}}}());this.checkDistances = function () {if ( !_this.noZoom || !_this.noPan ) {if ( _eye.lengthSq() > _this.maxDistance * _this.maxDistance ) {_this.object.position.addVectors( _this.target, _eye.setLength( _this.maxDistance ) );}if ( _eye.lengthSq() < _this.minDistance * _this.minDistance ) {_this.object.position.addVectors( _this.target, _eye.setLength( _this.minDistance ) );}}};this.update = function () {_eye.subVectors( _this.object.position, _this.target );if ( !_this.noRotate ) {_this.rotateCamera();}if ( !_this.noZoom ) {_this.zoomCamera();}if ( !_this.noPan ) {_this.panCamera();}_this.object.position.addVectors( _this.target, _eye );_this.checkDistances();_this.object.lookAt( _this.target );if ( lastPosition.distanceToSquared( _this.object.position ) > EPS ) {_this.dispatchEvent( changeEvent );lastPosition.copy( _this.object.position );}};this.reset = function () {_state = STATE.NONE;_prevState = STATE.NONE;_this.target.copy( _this.target0 );_this.object.position.copy( _this.position0 );_this.object.up.copy( _this.up0 );_eye.subVectors( _this.object.position, _this.target );_this.object.lookAt( _this.target );_this.dispatchEvent( changeEvent );lastPosition.copy( _this.object.position );};// listenersfunction keydown( event ) {if ( _this.enabled === false ) return;window.removeEventListener( 'keydown', keydown );_prevState = _state;if ( _state !== STATE.NONE ) {return;} else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && !_this.noRotate ) {_state = STATE.ROTATE;} else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && !_this.noZoom ) {_state = STATE.ZOOM;} else if ( event.keyCode === _this.keys[ STATE.PAN ] && !_this.noPan ) {_state = STATE.PAN;}}function keyup( event ) {if ( _this.enabled === false ) return;_state = _prevState;window.addEventListener( 'keydown', keydown, false );}function mousedown( event ) {if ( _this.enabled === false ) return;event.preventDefault();event.stopPropagation();if ( _state === STATE.NONE ) {_state = event.button;}if ( _state === STATE.ROTATE && !_this.noRotate ) {_rotateStart.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );_rotateEnd.copy( _rotateStart );} else if ( _state === STATE.ZOOM && !_this.noZoom ) {_zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );_zoomEnd.copy(_zoomStart);} else if ( _state === STATE.PAN && !_this.noPan ) {_panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );_panEnd.copy(_panStart)}document.addEventListener( 'mousemove', mousemove, false );document.addEventListener( 'mouseup', mouseup, false );_this.dispatchEvent( startEvent );}function mousemove( event ) {if ( _this.enabled === false ) return;event.preventDefault();event.stopPropagation();if ( _state === STATE.ROTATE && !_this.noRotate ) {_rotateEnd.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );} else if ( _state === STATE.ZOOM && !_this.noZoom ) {_zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );} else if ( _state === STATE.PAN && !_this.noPan ) {_panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );}}function mouseup( event ) {if ( _this.enabled === false ) return;event.preventDefault();event.stopPropagation();_state = STATE.NONE;document.removeEventListener( 'mousemove', mousemove );document.removeEventListener( 'mouseup', mouseup );_this.dispatchEvent( endEvent );}function mousewheel( event ) {if ( _this.enabled === false ) return;event.preventDefault();event.stopPropagation();var delta = 0;if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9delta = event.wheelDelta / 40;} else if ( event.detail ) { // Firefoxdelta = - event.detail / 3;}_zoomStart.y += delta * 0.01;_this.dispatchEvent( startEvent );_this.dispatchEvent( endEvent );}function touchstart( event ) {if ( _this.enabled === false ) return;switch ( event.touches.length ) {case 1:_state = STATE.TOUCH_ROTATE;_rotateStart.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );_rotateEnd.copy( _rotateStart );break;case 2:_state = STATE.TOUCH_ZOOM_PAN;var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;_panStart.copy( getMouseOnScreen( x, y ) );_panEnd.copy( _panStart );break;default:_state = STATE.NONE;}_this.dispatchEvent( startEvent );}function touchmove( event ) {if ( _this.enabled === false ) return;event.preventDefault();event.stopPropagation();switch ( event.touches.length ) {case 1:_rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );break;case 2:var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;_touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;_panEnd.copy( getMouseOnScreen( x, y ) );break;default:_state = STATE.NONE;}}function touchend( event ) {if ( _this.enabled === false ) return;switch ( event.touches.length ) {case 1:_rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );_rotateStart.copy( _rotateEnd );break;case 2:_touchZoomDistanceStart = _touchZoomDistanceEnd = 0;var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;_panEnd.copy( getMouseOnScreen( x, y ) );_panStart.copy( _panEnd );break;}_state = STATE.NONE;_this.dispatchEvent( endEvent );}this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );this.domElement.addEventListener( 'mousedown', mousedown, false );this.domElement.addEventListener( 'mousewheel', mousewheel, false );this.domElement.addEventListener( 'DOMMouseScroll', mousewheel, false ); // firefoxthis.domElement.addEventListener( 'touchstart', touchstart, false );this.domElement.addEventListener( 'touchend', touchend, false );this.domElement.addEventListener( 'touchmove', touchmove, false );window.addEventListener( 'keydown', keydown, false );window.addEventListener( 'keyup', keyup, false );this.handleResize();// force an update at startthis.update();};THREE.TrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype );
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
