# threejs练习 **Repository Path**: dttx123/threejs_exercise ## Basic Information - **Project Name**: threejs练习 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2019-10-16 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # THREEJS 入门基础知识
## three.js是什么 ​ WebGL(Web Graphics Library)是一种3D绘图协议,它允许把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,WebGL可以为HTML5 Canvas提供硬件3D加速渲染,这样Web开发人员就可以借助系统显卡来在浏览器里更流畅地展示3D场景和模型。 ​ 使用WebGL原生的API来写3D程序非常复杂,需要相对较多的数学知识,对于前端开发者来说学习成本较高。而Three.js对WebGL提供的接口进行了非常好的封装,简化了很多细节,大大降低了学习成本,成为前端开发者完成3D绘图的得力工具,目前在github上star数量已经达到了将近4万+。
## 三大基本组件 three.js使用面向对象的方式来构建程序,包含3个基本对象: 场景(scene), 相机(camera), 以及一个渲染器(renderer)。 比如看春晚,场景对应于整个舞台,相机是拍摄镜头,渲染器用来把拍摄好的舞台画面显示在电视屏幕上, 有了这三样东西, 才能够使用相机将场景渲染到网页上去。 ![](./img/sence.png)
### 场景 场景是所有物体的容器,如果要显示一个苹果,就需要将苹果对象加入场景中。在Threejs中场景就只有一种,用THREE.Scene来表示,要构件一个场景也很简单,只要new一个对象就可以了,代码如下: ```js var scene = new THREE.Scene(); //创建场景 ```
### 相机 相机就像人的眼睛一样,人站在不同位置,抬头或者低头都能够看到不同的景色。 场景只有一种,但是相机却又很多种, 不同的相机呈相的结果不同, 可以用不同的场景, (比如人像,风景,微距), 对开发者来说,只要设置不同的相机参数,即可; ```js // 创建透视相机 var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000); scene.add(camera); //添加相机 ```
### 渲染器 ​ 渲染器的作用就是将相机拍摄出的画面在浏览器中呈现出来。渲染器决定了渲染的结果应该画在页面的什么元素上面,并且以怎样的方式来绘制。three.js中有很多种类的渲染器,例如webGLRenderer、canvasRenderer、SVGRenderer,通常使用的是webGL渲染器。 ```js var renderer = new THERR.WebGLRenderer(); // 创建webGL渲染器 renderer.render(scene,camera); // 渲染 ``` 创建好染器后,需要调用render方法将之前创建好的场景和相机相结合从而渲染出来,即调用渲染器的render方法。
### 第一个场景 下面的代码, 我们将建立一个场景和一个旋转的立方体: ```js My first Three.js app ```
## 轨道控制器 ​ 轨道控制器OrbitControls.js是一个神奇的控件,可以实现场和鼠标、键盘交互,让场景动起来,控制场景的旋转、平移,缩放; 轨道控制器本质上改变的并不是场景,而是相机的参数,相机的位置角度不同,同一个场景的渲染效果是不一样,比如一个相机绕着一个场景旋转,就像场景旋转一样。 OrbitControls是对Three.js正投影相机和透视投影相机对象进行封装的,你想深入了解相机控制器OrbitControls的每一个功能,可以阅读Three.js\examples\js\controls目录下的OrbitControls.js 文件 **构造函数参数数说明** ```js new THREE.OrbitControls(object: Camera,domElement: HTMLDOMElement) // object: 控制的相机 // domElement: 可选的,指定在特定的元素(例如画布 renderer.domElement)上工作 ``` **属性:** |属性名|说明| |--|--| |autoRotate| Boolean 默认false。设定为true时,相机自动围绕目标旋转但必须在animation中循环调用update();| |autoRotateSpeed| Float 当前者为true时默认2.0,代表每轮60fps用时30s,值越小转动越慢| |rotateSpeed| Float 旋转速度(ORBIT的旋转速度,鼠标左键),默认1| |domElement| HTMLDOMElement 侦听鼠标/触摸事件,必须在构造函数中传递,用作特性值更改后不会重新设置事件侦听器 默认是整个文档| |enableDamping| Boolean 默认false。设置为true则启用阻尼(惯性),用来给控制相机一个重量,必须调用update()在你的animation循环中| |dampingFactor| Float 前者为true时使用阻尼惯性(可理解为阻止向一个方向移动)| |enabled| Boolean 是否启用控件,默认true| |enableKeys| Boolean 能否用键盘控制,默认true ←↑→↓四个键控制物体的移动| |keys| Object 控制相机平移的四个键。默认四个箭头键{LEFT: 37,UP: 38,RIGHT: 39,DOWM:40} 所有的键值| |enablePan| Boolean 相机平移,默认true| |panSpeed| Float 移动的速度,默认1| |keyPanSpeed| Float 相机平移的速度,默认每按一次控制方向键移动7.0像素| |enableRotate| Boolean 水平垂直旋转相机,默认true。只想控制单轴,通过PolarAngle/AzimuthAngle的最小值和最大值设置为相同的值,这将导致垂直| |maxAzimuthAngle| Float 水平旋转,范围Math.PI~Math.PI 或者Infinity 默认Infinity| |minAzimuthAngle| Float 水平旋转,范围Math.PI~Math.PI 或者Infinity 默认Infinity| |maxPolarAngle| Float 垂直旋转,范围0~Math.PI 默认Math.PI| |minPolarAngle| Float 垂直旋转,范围0~Math.PI 默认0| |maxDistance| Float 拉远镜头(只能用在PerspectiveCamera),默认Infinity| |minDistance| Float 拉近镜头,默认0| |maxZoom| Float 拉远镜头(只能用在OthorgraphicCamera),默认Infinity| |minZoom| Float拉近镜头,默认0| |mouseButton| Object {ORBIT: THREE.MOUSE.LEFT,ZOOM: THREE.MOUSE.MIDDLE,PAN: THREE.MOUSE.RIGHT} 鼠标控制缩放移动和旋转| |object| Camera 正在控制的相机| |position0| Vector3 在reset()和saveState()内部使用| |screenSpacePaning| Boolean 平移时摄像机位置的转换。true,相机的平移在屏幕空间;false,摄像机在与摄像机向上方向正交的平面上平移,默认false| |target| Vector3在reset()和saveState()内部使用| |zoom0| Vector3 在reset()和saveState()内部使用| |zoomSpeed| Float zoom(变焦)的速度,默认1| **方法:** | 方法名 | 说明 | | ------------------- | ------------------------------------------------------------ | | dispose() | null 移除所有的事件监听 | | getAzimuthalAngle() | radians 获得用弧度表示的当前水平旋转角度 | | getPolarAngle() | radians获得用弧度表示的当前垂直旋转角度 | | reset() | null 通过最近一次调用saveState()或者初始状态来重置为当前的状态 | | saveState() | null 保存当前控制的状态,可以稍后通过reset()来恢复 | | update() | false 更新控件,在手动改变了摄像机的钻换后必须调用。在设置了autoRotate或enableDamping时也要在循环中调用 | **事件** |事件名称|说明| |-|-| |change|OrbitControls的变化事件| 对于一个静态的场景,可能不需要一直周期性调用渲染函数渲染场景,而是鼠标旋转缩放场景的时候才重新渲染,就可以通过OrbitControls的变化事件change监听触发函数调用渲染函数render。 ```js // 渲染函数 function render() { renderer.render(scene, camera); } varcontrols = newTHREE.OrbitControls(camera); //监听鼠标事件,触发渲染函数,更新canvas画布渲染效果 controls.addEventListener('change', render); ``` ## dat.GUI.js 界面组件 dat.GUI 是一个轻量级的图形用户界面库,使用这个库可以很容易地创建出能够改变代码变量的界面组件 ![](./img/datGui.png) ### 使用步骤 1 引包 ```js ``` 2 定义一个 JavaScript 对象(如:controls),该对象中保存要通过 dat.GUI 改变的属性 ```js var controls = new function () { this.rotationSpeed = 0.02; //...... }; ``` 3 接下来需要将这个 JavaScript 对象传递给 dat.gui 对象,并设置各个属性的取值范围 ```js var gui = new dat.GUI(); gui.add(controls, 'rotationSpeed', 0, 0.5); ``` 4 最后当用户对 dat.GUI 控件进行操作时,controls 里的属性值也会同步修改。在程序中直接引用这个属性值即可 ### 控件类型 > dat.GUI 会根据我们设置的属性类型来渲染使用不同的控件。 #### 数字类型(Number) ```js // contorls 存放需要改变的属性 var controls = new function () { this.rotationSpeed = 0.02; }; ``` + 如果没有设置限制条件,则为一个 input 输入框。 ```js var gui = new dat.GUI(); gui.add(controls, 'rotationSpeed').name('旋转速度'); // name方法指定别名 ``` + 可以设置最小值最大值范围,则显示为 slider 滑块组件(当然右侧还是有 input 输入) ```js var gui = new dat.GUI(); gui.add(controls, 'rotationSpeed', 0, 0.5); ``` + 还可以只单独限制最小值或者最大值,这个同样为一个 input 输入框。 ```js var gui = new dat.GUI(); gui.add(controls, 'rotationSpeedX').min(0); gui.add(controls, 'rotationSpeedY').max(10); ``` + 可以配合 step 限制步长。 ```js var gui = new dat.GUI(); gui.add(controls, 'rotationSpeedX').step(0.5); gui.add(controls, 'rotationSpeedY', 0, 3).step(0.5); gui.add(controls, 'rotationSpeedZ').max(10).step(0.5); ``` + 如果数字只是有限的几种固定值,那还可以使用下拉框的形式。 ```js var gui = new dat.GUI(); gui.add(controls, 'rotationSpeed', { Stopped: 0, Slow: 0.02, Fast: 5 }); ``` #### 字符串类型(String) + 默认情况下就是一个 input 输入框。 ```js var controls = new function () { this.site = "hangge.com" }; var gui = new dat.GUI(); gui.add(controls, 'site'); ``` + 只是有限的几种固定值,那还可以使用下拉框的形式。 ```js var controls = new function () { this.site = "hangge.com" }; var gui = new dat.GUI(); gui.add(controls, 'site', [ 'google.com', 'hangge.com', '163.com' ]); ``` #### 布尔类型(Boolean ) + 使用复选框(Checkbox)的形式控制 ```js var controls = new function () { this.visible = true }; var gui = new dat.GUI(); gui.add(controls, 'visible'); ``` #### 自定义函数(Function) 使用按钮(button)的形式控制,点击按钮会调用相应的方法。 ```js var controls = new function () { this.hello = function() { alert("欢迎访问 hangge.com"); } }; var gui = new dat.GUI(); gui.add(controls, 'hello'); ``` #### 颜色值 dat.GUI 一共提供了 4 种类型颜色输入控制:CSS、RGB、RGBA、Hue(注意:颜色使用 addColor 方法添加控件) ```js var controls = new function () { this.color0 = "#ffae23"; // CSS string this.color1 = [0, 128, 255]; // RGB array this.color2 = [0, 128, 255, 0.3]; // RGB with alpha this.color3 = {h: 350, s: 0.9, v: 0.3}; // Hue, saturation, value }; var gui = new dat.GUI(); gui.addColor(controls, 'color0'); gui.addColor(controls, 'color1'); gui.addColor(controls, 'color2'); gui.addColor(controls, 'color3'); ``` ### 事件监听 对于面板中的每一个控制项,我们都可以设置 onChange 和 onFinishChange 监听事件。 ```js var controls = new function () { this.speed = 1; }; var gui = new dat.GUI(); var speedController = gui.add(controls, 'speed', 0, 5); //对应控制项值改变时响应(比如拖动滑块过程中) speedController.onChange(function(value) { //value 要改变的数据 console.log("onChange:" + value) }); //对应控制项值修改完毕响应 speedController.onFinishChange(function(value) { console.log("onFinishChange" + value) }); ``` ### 选项组 可以使用文件夹给选项分组 ```js var gui = new dat.GUI(); // 第一组 var f1 = gui.addFolder('Flow Field'); f1.add(text, 'speed'); f1.add(text, 'noiseStrength'); // 第二组 var f2 = gui.addFolder('Letters'); f2.add(text, 'growthSpeed'); f2.add(text, 'maxSize'); f2.add(text, 'message'); // 展开第二组 f2.open(); ``` ## 把模型渲染到场景 下面代码是将一个立方体添加到场景中: ```js // 1-创建立方体几何模型 var geometry = new THREE.BoxGeometry(1, 1, 1); // 2-创建基础材质对象 var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); // 3-创建网格模型 var cube = new THREE.Mesh(geometry, material); // 4-将网格模型添加到 场景中 scene.add(cube); ```