入门开发 创建世界模型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 const scene = new three.Scene ()const camera = new three.PerspectiveCamera ( 45 , window .innerWidth /window .innerHeight , 0.1 , 1000 ) const render = new three.WebGLRenderer () render.setSize (window .innerWidth ,window .innerHeight ) document .body .appendChild (render.domElement )const geometry = new three.BoxGeometry (1 ,1 ,1 )const matetry = new three.MeshBasicMaterial ({color :"red" })const cube = new three.Mesh (geometry,matetry)scene.add (cube) camera.position .z = 5 camera.position .x = 5 camera.position .y = 5 camera.lookAt (0 ,0 ,0 ) const axesHelper = new three.AxesHelper (5 ) scene.add (axesHelper) function animation ( ){ requestAnimationFrame (animation) cube.rotation .x += 0.01 cube.rotation .y += 0.01 render.render (scene,camera) } animation ()
轨道控制器 定义: Orbit controls(轨道控制器)可以使得相机围绕目标进行轨道运动。
1 2 3 4 5 6 7 import {OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js' const controls = new OrbitControls (camera,render.domElement )controls.enableDamping =true controls.dampingFactor =0.01
前置知识 三维向量(Vector3) 该类表示的是一个三维向量(3D vector )。 一个三维向量表示的是一个有顺序的、三个为一组的数字组合(标记为x、y和z), 可被用来表示很多事物,例如:
一个位于三维空间中的点。
一个在三维空间中的方向与长度的定义。在three.js中,长度总是从(0, 0, 0)到(x, y, z)的 Euclidean distance (欧几里德距离,即直线距离), 方向也是从(0, 0, 0)到(x, y, z)的方向。
任意的、有顺序的、三个为一组的数字组合。
其他的一些事物也可以使用二维向量进行表示,比如说动量矢量等等; 但以上这些是它在three.js中的常用用途。
构造函数 Vector3( x : Float, y : Float, z : Float )
x - 向量的x值,默认为0 。 y - 向量的y值,默认为0 。 z - 向量的z值,默认为0 。
欧拉角(Euler) 表示 Euler 的类。
欧拉角描述一个旋转变换,通过指定轴顺序和其各个轴向上的指定旋转角度来旋转一个物体。
构造器 Euler( x : Float, y : Float, z : Float, order : String )
x - (optional) 用弧度表示x轴旋转量。 默认值是 0 。 y - (optional) 用弧度表示y轴旋转量。 默认值是 0 。 z - (optional) 用弧度表示z轴旋转量。 默认值是 0 。 order - (optional) 表示旋转顺序的字符串,默认为’XYZ’(必须是大写)。
三维物体属性 position定义:表示对象的局部位置,有父元素根据父元素的位置进行移动,没得父元素则是根据世界坐标系来进行移动,是一个三维向量。 position.x/y/z 可单独设置某个坐标的位置。positon.set(三维坐标)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 const geometry = new three.BoxGeometry (1 ,1 ,1 )const matetry = new three.MeshBasicMaterial ({color :"red" })const matetry1 = new three.MeshBasicMaterial ({color :"green" })const parentCube = new three.Mesh (geometry,matetry1) const cube = new three.Mesh (geometry,matetry)parentCube.position .set (-3 ,0 ,0 ) cube.position .set (3 ,0 ,0 ) cube.scale .set (2 ,2 ,2 ) parentCube.add (cube) scene.add (parentCube)
scale定义:一个三维物体的局部缩放,有父级则相对于父级的尺寸进行缩放,没有父级则是默认值。也是一个三维向量。scale.set(三维坐标)
1 2 3 4 5 6 7 8 const parentCube = new three.Mesh (geometry,matetry1) const cube = new three.Mesh (geometry,matetry)parentCube.scale .set (2 ,2 ,2 ) cube.scale .set (2 ,2 ,2 ) parentCube.add (cube) scene.add (parentCube)
rotation定义: 物体的局部旋转,以弧度来表示。 如果有父级物体 他会收到父级物体的旋转,会在父级的基础上再进行旋转,反之则不会。rotation.x/y/z 或 rotation.set(三维坐标)
1 2 3 // 旋转:局部旋转 会受到父元素的旋转影响 parentCube.rotation.x = Math.PI/4 cube.rotation.x = Math.PI/4
屏幕自适应 监听window 视窗大小让画面实时变化
1 2 3 4 5 6 7 8 9 window .addEventListener ('resize' ,()=> { render.setSize (window .innerWidth ,window .innerHeight ) camera.aspect = window .innerWidth / window .innerHeight camera.updateProjectionMatrix () })
全屏 1 2 3 4 5 6 7 8 9 10 11 12 13 // 开启全屏 const btn = document.createElement('button') btn.innerHTML= '全屏' btn.addEventListener('click',()=>{ // 要body进行全屏 而不是画布 不然按钮就看不见了 // render.domElement.requestFullscreen() document.body.requestFullscreen() }) btn.style.position = 'absolute' btn.style.top = '20px' btn.style.left = '20px' btn.style.zIndex = '9999' document.body.appendChild(btn)
空间节点Object3D 使用情况:如果一个模块空间含有多个物体的情况,在其某个节点下添加子节点,此时缩放这个节点,它的所属空间也会跟着缩放,此时子节点的物体也会跟着缩放。避免这一情况的发生,我们会创建一个空的空间节点来来装这些空间,将节点与它的子节点装在其中,无需进行嵌套,因为此时这两个节点的远点都是相对空节点的原点。
材质(Material)和几何体(Geometry)可以被多个网格(Mesh)对象使用。比如在不同的位置画两个蓝色立方体,我们会需要两个网格(Mesh)对象来代表每一个立方体的位置和方向。但只需一个几何体(Geometry)来存放立方体的顶点数据,和一种材质(Material)来定义立方体的颜色为蓝色就可以了。两个网格(Mesh)对象都引用了相同的几何体(Geometry)和材质(Material)
材质:MeshBasicMaterial:不受光照影响, MeshPhongMaterial:受光照影响
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 const render1 = new three.WebGL1Renderer() console.log(this.threeDom.style.width); render1.setSize(w,h) this.threeDom.appendChild(render1.domElement) //设置相机的位置 与朝向 camere.position.set(0, 10, 0); //y轴距离10处 camere.up.set(0, 0, 1);//z轴在上 camere.lookAt(0, 0, 0);//看向原点 const arr = [] //设置一个球形缓存体的设置 const radius = 1 const widthSegmets = 360 const heightSegments = 360 //只在场景中进行添加 const sphereGemotry = new three.SphereGeometry(radius,widthSegmets,heightSegments) //单独创建一个空余的空间来 const color = 0xffffff; const intensity = 100; const light = new three.PointLight(color, intensity); light.position.set(-2,0,0) scene.add(light); //创建第一层空间 用于太阳 与含有嵌套关系的地月系统的第二层空间 const systemObje = new three.Object3D() arr.push(systemObje) const sunMaterial = new three.MeshPhongMaterial({emissive:0xffff00}) const sunMesh = new three.Mesh(sphereGemotry,sunMaterial) sunMesh.scale.set(2,2,2) systemObje.add(sunMesh) arr.push(sunMesh) //地月关系 创建第二层空间 其中含有嵌套关系 const other = new three.Object3D() other.position.x = 10 arr.push(other) systemObje.add(other) const childMaterial = new three.MeshPhongMaterial({color: "#303438",emissive: "440fad"}) const childMseh = new three.Mesh(sphereGemotry,childMaterial) childMseh.scale.set(1.5,1.5,1.5) other.add(childMseh) arr.push(childMseh) const moonMaterial = new three.MeshPhongMaterial({color: "#303438",emissive: 0x112244}) const moonMesh = new three.Mesh(sphereGemotry,moonMaterial) moonMesh.position.set(3,0,0) arr.push(moonMesh) other.add(moonMesh) scene.add(systemObje) const controls = new OrbitControls(camere, render1.domElement); const axeHelper = new three.AxesHelper(50); scene.add(axeHelper); function animation() { arr.forEach(item=>{ item.rotation.y += 0.01; }) controls.update() render1.render(scene, camere); requestAnimationFrame(animation); } animation();