作为前端开发者,谁不喜欢这样的所见即所得的快乐呢?
构建场景 物理引擎 塑造模型
说起来酷炫,但是实际学起来实在是头大,WegGl的管道着色器基本上写起来和学一门新的语言一样,ThreeJs的话 教程又没那么多,实在是费力。
最近发现了国外大佬的课,分享一下自己的ThreeJs学习路程~
在文章中用到的代码 都会在附在附录上~
接下来就是干货时间:
首先建立HTML文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>03 - Basic Scene</title>
</head>
<body>
<canvas class="webgl"></canvas>
<script src="./three.min.js"></script>
<script src="./script.js"></script>
</body>
</html>
JS文件
// // Canvas
// const canvas = document.querySelector('canvas.webgl')
// // Sizes
// const sizes = {
// width: 800,
// height: 600
// }
// // Scene
// const scene = new THREE.Scene()
// // Object
// const cubeGeometry = new THREE.BoxGeometry(1, 1, 1)
// const cubeMaterial = new THREE.MeshBasicMaterial({
// color: '#ff0000'
// })
// const cubeMesh = new THREE.Mesh(cubeGeometry, cubeMaterial)
// scene.add(cubeMesh)
// // Camera
// const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height)
// camera.position.z = 3
// scene.add(camera)
// // Renderer
// const renderer = new THREE.WebGLRenderer({
// canvas: canvas
// })
// renderer.setSize(sizes.width, sizes.height)
// renderer.render(scene, camera)
const scene = new THREE.Scene()
const geometry = new THREE.BoxGeometry(1,1,1)
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 })
const mesh = new THREE.Mesh(geometry,material)
scene.add(mesh)
const sizes = {
width: 800,
height: 600
}
const camera = new THREE.PerspectiveCamera(75,sizes.width/sizes.height)
camera.position.z = 3
scene.add(camera)
const canvas = document.querySelector('.webgl')
const render = new THREE.WebGLRenderer({
canvas:canvas
})
render.setSize(sizes.width,sizes.height)
render.render(scene,camera)
最后记得再去下载THREEJS文件 并且引入就可以啦!
Three Js 四大要素
1.包含一些对象的场景 Scene
2.一些对象 Object
3.摄像机 Camera
4.渲染器 Render
Scene
const scene = new THREE.Scene()
Object
创建对象,我们需要先创建一个Mesh
Mesh
一个Mesh 是几何(形状)和材料(外观)的组合。
那么我们创建Mesh 对应就需要先创建几何Geomotry ,以及材料Material
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 })
小Tips:
颜色16进制表示 分别表示 R G B 即 红 绿 蓝 ,颜色深度分别从0 到 f
# ff0000
表示为红色
ff => 红色满格
00 => 不要绿色
00 => 不要蓝色
所以如上ff0000就表示纯红色了
创建好geometry
和material
就可以通过THREE.Mesh()
来合并生成一个Mesh对象了。
const mesh = new THREE.Mesh(geometry,material)
添加对象
创建Mesh 之后 一定记得像Scen中进行添加,不然Camera是看不到它的
scene.add(mesh)
Camera
1.相机不可见
2.可以设置多个相机,但是render的时候 只能有一个
常规的 我们创建PerspectiveCamera
透视相机,可以实现使近处的物体看起来比远处的物体更突出的效果。
设置相机需要像个参数
View 视角
视野是你的视角有多大。如果您使用非常大的角度,您将能够同时看到各个方向,但失真很大,因为结果将绘制在一个小矩形上。如果您使用小角度,则事物看起来会放大。视野(或 fov
)以度数表示,对应于垂直视角。在本练习中,我们将使用 75
度角。
小视角:
大视角:
Size 纵横比
在大多数情况下,纵横比是画布的宽度除以其高度。我们暂时没有指定任何宽度或高度,但我们稍后需要。同时,我们将创建一个具有临时值的对象,我们可以重用它。
不要忘记将相机添加到场景中。一切都应该可以在不将相机添加到场景中的情况下工作,但稍后可能会导致错误
相机位置
一定记得设置camera的position 或者 rotation 或者scale
否则 摄像机会处于 整个物体的内部,无法看到任何东西
const camera = new THREE.PerspectiveCamera(75,sizes.width/sizes.height)
camera.position.z = 3
scene.add(camera)
Object
操作ThreeJS 中的 对象 可以帮助我们在后续实现一些动画的效果
之前我们试过position
来移动camera的位置,达到不同的视角
后续 我们可以一共有 4 个属性可以转换场景中的对象
-
position
(移动物体) -
scale
(调整对象大小) -
rotation
(旋转对象) -
quaternion
(类似旋转对象)注意我们改变object的位置,一定要在render.renderer 函数调用之前,否则就不会生效了。
Position
x 是向右的,y轴是向上的,z轴是向后的(forward to camera)
我们可以通过操作Mesh来 变换
因为Mesh 即成雨Object.3D 且 代表着一个具体的模块,即由形状和材质两部分组成。
mesh.position.x = 0.7
mesh.position.y = - 0.6
mesh.position.z = 1
//或者
mesh.position.set(0.7, - 0.6, 1)
Length
Position 设置后 是一个Vector3[3维向量],因此我们可以求的具体的值
mesh.position.length()
这样可以得到一个具体的向量的长度。
同时,如果我们对两个Vectore3 需要知道他们的距离,可以使用distanceTo
函数
//当前mesh与相机向量的距离
mesh.position.distanceTo(camera.position)
//与向量(0,1,2)的距离
mesh.positon.distanceTo(new THREE.Vector3(0,1,2))
归一化【标准化】
相当于 将当前向量归一化为标准向量,只需要使用normalize
函数即可。
mesh.position.distanceTo(camera.position)
//此时 mesh的length是1
辅助线
/**
* Axes Helper
*/
const axesHelper = new THREE.AxesHelper(2)
scene.add(axesHelper)
AxesHelper
的参数表示辅助线的长度
绿色 - y轴
红色 - x轴
蓝色 - z轴
默认情况下,Camera是对准z轴的,也就是如果我们不移动camera的x , y 那么会看到如下的画面
Scale
按某个方向 缩放
mesh.scale.x = 2
mesh.scale.y = 0.25
mesh.scale.z = 0.5
mesh.scale.set(2,0.5,0.5)
Rotation
1.旋转
旋转以当前的轴为中心 旋转度数
- 如果你在
y
轴上旋转,你可以把它想象成一个旋转木马。 - 如果你在
x
轴上旋转,你可以想象你正在旋转你将要乘坐的汽车的轮子。 - 如果你在
z
轴上旋转,你可以想象你正在旋转你将要乘坐的飞机前面的螺旋桨。
默认2PI 为一个圆周
mesh.rotation.x = Math.PI * 0.25
mesh.rotation.y = Math.PI * 0.25
但是注意了,在普通的旋转中,无论我们在js中 rotation的顺序如何,都是按照 先x 再y 再z 进行旋转的,然而当我们执行x轴的旋转操作后,此时再执行y轴 就已经和初始的y轴不一致了,因此 我们需要通过加锁来进行设置
object.rotation.reorder('YXZ')
//1.此处XYZ为字符串 2.一定要大写
设置后即表示,按照 先y轴 再x轴 再z轴的顺讯进行旋转。
Look At
Camera.lookat(Vector3)
表示 将摄像机指向目标的向量
camera.lookAt(new THREE.Vector3(0, - 1, 0))
即表示将摄像机指向 0 -1 0 的向量位置
当然,我们也可以使用camera.lookAt(mesh.position)
,此时我们的mesh就会出现在屏幕的正中央。
Group
需要对一个object
进行多次变换操作的时候,我们可以通过创建一个group
然后,直接移动group即可。