前端Three.js入门(二)

57 阅读4分钟

前言

基于前面的学习,我们继续深入

3-坐标辅助器与轨道控制器

可能大家大家进入官方文档很卡,大家可以把源码下载下来,然后在vscode终端直接npm run dev就能本地部署,打开之后点击docs即可进去。怎么部署呢?大家可以看b站这个视频: www.bilibili.com/video/BV1Gg…

1-坐标辅助器(axesHelper)

为了能更好的观察,我们可以引入一个坐标辅助器,代码如下:

//添加世界坐标辅助器
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);

然后我们就能在页面上看见x,y轴。为什么看不见z轴?因为它在我们正对面,换句话来说,问我们的视角就是z轴。那我们怎么才能看到z轴呢?可以设置: camera.lookAt(3, 0, 0)偏移之后我们就能看见z轴啦!

2-轨道控制器(controls)

为什么要加入这个?首先呢我们为了方便开发,会取消第一节所讲的自动旋转。然后我们加入轨道控制器,再加入相应的内容(后面会讲到),就能更好的开发我们的页面了

首先我们引入控制器:

//导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
//创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);//renderer.domElement监听的是canvas事件,若想换别的也行如document.body,记住body要设置宽高!
//带阻尼,带有一定的惯性,优化手感哈哈
controls.enableDamping = true;
//设置阻尼系数
controls.dampingFactor = 0.05;
//也可以设置旋转速度
controls.autoRotate=0.05;
//在渲染函数里面更新
//渲染循环
function animate() {
  controls.update(); // 只更新控制器内部状态
  requestAnimationFrame(animate);
  // cube.rotation.x += 0.01;除去自动旋转
  // cube.rotation.y += 0.01;
  renderer.render(scene, camera);
}

animate();
//相关配置可以去看官方文档

e6ad57ed79ea78c71a712934b81efb1.png

4-物体位移与父子元素

1. 物体位移基础

1.1 position属性

所有继承自Object3D的对象(如Mesh、Group)都包含position属性:

cube.position.set(x, y, z)
  • 使用右手坐标系:X轴右,Y轴上,Z轴朝向屏幕外
  • 默认坐标为(0,0,0)

1.2 坐标系类型

  • 局部坐标系 (Local Space):相对于父容器的坐标
  • 世界坐标系 (World Space):场景中的绝对坐标

2. 父子元素关系

2.1 创建父子关系

parent.add(child)
  • 子对象继承父对象的变换(位移/旋转/缩放)
  • 父子关系形成场景图(Scene Graph)结构

2.2 位移继承特性

操作对象局部坐标变化世界坐标变化
父物体保持不变改变
子物体相对父物体自动更新

3. 位移叠加原理

3.1 变换矩阵计算

物体最终位置由矩阵乘法决定:

World Matrix = Parent World Matrix × Local Matrix

3.2 示例场景

/* 创建父子物体 */
const parent = new THREE.Mesh(geometry, material)//材质的话可以颜色跟儿子不一样,容易区分
const child = new THREE.Mesh(geometry, material)

parent.add(child)

/* 设置位移 */
parent.position.set(2, 0, 0) // 父物体右移2单位
child.position.set(0, 1, 0) // 子物体在父坐标系中上移1单位

最终世界坐标计算:

子物体世界坐标 = 父物体位置 + 子物体局部位置
              = (2,0,0) + (0,1,0) 
              = (2,1,0)

4. 注意事项

  1. 性能优化

    • 避免每帧更新矩阵,需要时手动调用updateMatrixWorld()
  2. 坐标系混淆

    • 使用getWorldPosition()获取世界坐标:
    const worldPosition = new THREE.Vector3()
    child.getWorldPosition(worldPosition)
    
  3. 复合变换 当存在旋转/缩放时,位移计算会受矩阵乘法顺序影响


5. 完整代码示例

// 场景初始化
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000)
const renderer = new THREE.WebGLRenderer()

// 创建物体
const geometry = new THREE.BoxGeometry()
const material = new THREE.MeshBasicMaterial({color: 0x00ff00})
//const parentmaterial = new THREE.MeshBasicMaterial({color: 0x ff00ff00})
// 创建父子物体
const parent = new THREE.Mesh(geometry, material)
const child = new THREE.Mesh(geometry, material)
parent.add(child)

// 设置初始位置
parent.position.set(2, 0, 0)    // 父物体X轴+2
child.position.set(0, 1, 0)     // 子物体在父坐标系中Y+1

// 将父物体加入场景
scene.add(parent)

// 验证世界坐标
const worldPos = new THREE.Vector3()
child.getWorldPosition(worldPos)
console.log('World Position:', worldPos) // 输出 (2,1,0)

// 相机位置
camera.position.z = 5

0f4bf930ef6d34bf0ac275335b06811.png

c54b985b5b64d85e954eba76372d0d4.png

搜索vector3可以进入查看

总结

  • 父子关系通过add()方法建立,形成层级变换链
  • 局部坐标通过矩阵乘法转换为世界坐标
  • 使用getWorldPosition()获取准确世界空间位置
  • 注意变换顺序对最终结果的影响