THREE.js 第一部分 canvas_ascii_effect.html 内容分析

来源:互联网 发布:c语言delay头文件 编辑:程序博客网 时间:2024/05/29 16:36

因为之后会用到图表插件开发,需要用到THREE.js D3.js ECharts。

D3部分因为已经开发了几个插件部分,个人觉得难点在于数据的预处理与结构的变换,不同于从数据库中的SELECT出的数据部分,可能更多的是需要配合D3.json等接口数据处理的格式,整合数据。

ECharts部分的图表开发,相对于会更加的简练。

THREE.js 感觉不太适用于通用的图表展示,本身是一个实时渲染的过程,个人感觉之后的发展方向会向简单动画部分或者片头去展示,或者是更加高大上的图表,抽象图表部分。


贴代码:

var container, stats;var camera, controls, scene, renderer;var effect;var sphere, plane;//获取js当前运行的事件var start = Date.now();//初始化 属于惯用方法init();//动画操作 属于惯用方法animate();function init() {    //窗口的大小var width = window.innerWidth || 2;var height = window.innerHeight || 2;//创建div部分 属于惯用方法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 change the view';container.appendChild( info );//镜头部分camera = new THREE.PerspectiveCamera( 70, width / height, 1, 1000 );camera.position.y = 150;camera.position.z = 500;//控制器部分controls = new THREE.TrackballControls( camera );//场景部分scene = new THREE.Scene();scene.background = new THREE.Color( 0xf0f0f0 );//灯光效果,点光源var light = new THREE.PointLight( 0xffffff );light.position.set( 500, 500, 500 );scene.add( light );//光源颜色,光强度var light = new THREE.PointLight( 0xffffff, 0.25 );light.position.set( - 500, - 500, - 500 );scene.add( light );//几何 形状 球体 这种材质对光照有反应,用于创建暗淡的不发光的物体sphere = new THREE.Mesh( new THREE.SphereGeometry( 200, 20, 10 ), new THREE.MeshLambertMaterial() );scene.add( sphere );                //几何 形状 平面骨架 对光照无感,给几何体一种简单的颜色或显示线框plane = new THREE.Mesh( new THREE.PlaneBufferGeometry( 400, 400 ), new THREE.MeshBasicMaterial( { color: 0xe0e0e0 } ) );plane.position.y = - 200;plane.rotation.x = - Math.PI / 2;scene.add( plane );//渲染renderer = new THREE.CanvasRenderer();renderer.setSize( width, height );container.appendChild( renderer.domElement );effect = new THREE.AsciiEffect( renderer );effect.setSize( width, height );container.appendChild( effect.domElement );stats = new Stats();container.appendChild( stats.dom );//添加事件监听window.addEventListener( 'resize', onWindowResize, false );}//页面调整大小,可以理解为鼠标滚轮变化function onWindowResize() {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize( window.innerWidth, window.innerHeight );effect.setSize( window.innerWidth, window.innerHeight );}//动画部分function animate() {    //固定格式requestAnimationFrame( animate );stats.begin();render();stats.end();}//渲染操作function render() {var timer = Date.now() - start;sphere.position.y = Math.abs( Math.sin( timer * 0.002 ) ) * 150;sphere.rotation.x = timer * 0.0003;sphere.rotation.z = timer * 0.0002;controls.update();effect.render( scene, camera );}
代码部分添加了部分注释。

采取一步步的分析的过程:

1.针对引用的TrackballControls看一下源码部分

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.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(),_movePrev = new THREE.Vector2(),_moveCurr = new THREE.Vector2(),_lastAxis = new THREE.Vector3(),_lastAngle = 0,_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' };// methods//处理缩放的问题this.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 getMouseOnScreen( pageX, pageY ) {vector.set(( pageX - _this.screen.left ) / _this.screen.width,( pageY - _this.screen.top ) / _this.screen.height);return vector;};}() );//鼠标按住滑动var getMouseOnCircle = ( function () {var vector = new THREE.Vector2();return function getMouseOnCircle( pageX, pageY ) {vector.set(( ( pageX - _this.screen.width * 0.5 - _this.screen.left ) / ( _this.screen.width * 0.5 ) ),( ( _this.screen.height + 2 * ( _this.screen.top - pageY ) ) / _this.screen.width ) // screen.width intentional);return vector;};}() );//镜头滑动this.rotateCamera = ( function() {var axis = new THREE.Vector3(),quaternion = new THREE.Quaternion(),eyeDirection = new THREE.Vector3(),objectUpDirection = new THREE.Vector3(),objectSidewaysDirection = new THREE.Vector3(),moveDirection = new THREE.Vector3(),angle;return function rotateCamera() {moveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 );angle = moveDirection.length();if ( angle ) {_eye.copy( _this.object.position ).sub( _this.target );eyeDirection.copy( _eye ).normalize();objectUpDirection.copy( _this.object.up ).normalize();objectSidewaysDirection.crossVectors( objectUpDirection, eyeDirection ).normalize();objectUpDirection.setLength( _moveCurr.y - _movePrev.y );objectSidewaysDirection.setLength( _moveCurr.x - _movePrev.x );moveDirection.copy( objectUpDirection.add( objectSidewaysDirection ) );axis.crossVectors( moveDirection, _eye ).normalize();angle *= _this.rotateSpeed;quaternion.setFromAxisAngle( axis, angle );_eye.applyQuaternion( quaternion );_this.object.up.applyQuaternion( quaternion );_lastAxis.copy( axis );_lastAngle = angle;} else if ( ! _this.staticMoving && _lastAngle ) {_lastAngle *= Math.sqrt( 1.0 - _this.dynamicDampingFactor );_eye.copy( _this.object.position ).sub( _this.target );quaternion.setFromAxisAngle( _lastAxis, _lastAngle );_eye.applyQuaternion( quaternion );_this.object.up.applyQuaternion( quaternion );}_movePrev.copy( _moveCurr );};}() );//镜头缩放this.zoomCamera = function () {var factor;if ( _state === STATE.TOUCH_ZOOM_PAN ) {factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;_touchZoomDistanceStart = _touchZoomDistanceEnd;_eye.multiplyScalar( factor );} else {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 panCamera() {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 ) );_zoomStart.copy( _zoomEnd );}if ( _eye.lengthSq() < _this.minDistance * _this.minDistance ) {_this.object.position.addVectors( _this.target, _eye.setLength( _this.minDistance ) );_zoomStart.copy( _zoomEnd );}}};//更新页面部分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 );};// listeners//事件监听function 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 ) {_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );_movePrev.copy( _moveCurr );} 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 ) {_movePrev.copy( _moveCurr );_moveCurr.copy( getMouseOnCircle( 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();switch ( event.deltaMode ) {case 2:// Zoom in pages_zoomStart.y -= event.deltaY * 0.025;break;case 1:// Zoom in lines_zoomStart.y -= event.deltaY * 0.01;break;default:// undefined, 0, assume pixels_zoomStart.y -= event.deltaY * 0.00025;break;}_this.dispatchEvent( startEvent );_this.dispatchEvent( endEvent );}//触摸开始function touchstart( event ) {if ( _this.enabled === false ) return;switch ( event.touches.length ) {case 1:_state = STATE.TOUCH_ROTATE;_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );_movePrev.copy( _moveCurr );break;default: // 2 or more_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;}_this.dispatchEvent( startEvent );}//触摸移动function touchmove( event ) {if ( _this.enabled === false ) return;event.preventDefault();event.stopPropagation();switch ( event.touches.length ) {case 1:_movePrev.copy( _moveCurr );_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );break;default: // 2 or morevar 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;}}//触摸function touchend( event ) {if ( _this.enabled === false ) return;switch ( event.touches.length ) {case 0:_state = STATE.NONE;break;case 1:_state = STATE.TOUCH_ROTATE;_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );_movePrev.copy( _moveCurr );break;}_this.dispatchEvent( endEvent );}function contextmenu( event ) {if ( _this.enabled === false ) return;event.preventDefault();}//释放this.dispose = function() {this.domElement.removeEventListener( 'contextmenu', contextmenu, false );this.domElement.removeEventListener( 'mousedown', mousedown, false );this.domElement.removeEventListener( 'wheel', mousewheel, false );this.domElement.removeEventListener( 'touchstart', touchstart, false );this.domElement.removeEventListener( 'touchend', touchend, false );this.domElement.removeEventListener( 'touchmove', touchmove, false );document.removeEventListener( 'mousemove', mousemove, false );document.removeEventListener( 'mouseup', mouseup, false );window.removeEventListener( 'keydown', keydown, false );window.removeEventListener( 'keyup', keyup, false );};this.domElement.addEventListener( 'contextmenu', contextmenu, false );this.domElement.addEventListener( 'mousedown', mousedown, false );this.domElement.addEventListener( 'wheel', mousewheel, false );this.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();};
整个js中主要的作用是写定了事件处理部分,是整个页面的核心处理模块。

2.主要的难点就在于事件的处理与内容的渲染render,至于camera,scene,light部分,知道是什么内容和含义即可。

原创粉丝点击