当前位置:   article > 正文

three.js 细一万倍教程 从入门到精通(一)

three.js 细一万倍教程 从入门到精通(一)

目录

一、three.js开发环境搭建

1.1、使用parcel搭建开发环境

1.2、使用three.js渲染第一个场景和物体

1.3、轨道控制器查看物体

二、three.js辅助设置

2.1、添加坐标轴辅助器

2.2、设置物体移动

2.3、物体的缩放与旋转

缩放

旋转

2.4、应用requestAnimationFrame

2.5、通过Clock跟踪时间处理动画

2.6、Gsap动画库基本使用与原理

2.7、Gsap控制动画属性与方法

2.8、根据尺寸变化实现自适应画面

阻尼效果

自适应画面

2.9、调用js接口控制画布全屏和退出全屏

2.10、应用图形用户界面更改变量


一、three.js开发环境搭建

1.1、使用parcel搭建开发环境

第一步:创建空项目

第二步:终端输入

npm init

直接一路回车。

第三步:安装parcel

npm install parcel-bundler

接着,通过修改你的package.json来添加这些任务脚本

  1. "scripts": {
  2. "dev": "parcel src/index.html",
  3. "build": "parcel build src/index.html"
  4. },

第四步:创建src/index.html

第五步:终端输入命令

npm install parcel-bundler -dev

第六步:创建静态文件,引入静态文件

第七步:编写style.css代码

  1. * {
  2. margin: 0;
  3. padding: 0;
  4. }
  5. body {
  6. background-color: skyblue;
  7. }

第八步:安装threejs依赖

npm install three --save

第九步:编写main.js代码,看threejs是否安装成功

  1. import * as THREE from "three"
  2. console.log(THREE);

第十步:启动项目

1.2、使用three.js渲染第一个场景和物体

  1. import * as THREE from "three"
  2. // 1、创建场景
  3. const scene = new THREE.Scene()
  4. // 2、创建相机
  5. const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
  6. // 3、设置相机位置
  7. camera.position.set(0, 0, 10);
  8. scene.add(camera)
  9. // 添加物体
  10. // 创建几何体
  11. const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
  12. // 材质
  13. const cubeMaterial = new THREE.MeshBasicMaterial({color: 0xffff00});
  14. // 根据几何体和材质创建物体
  15. const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
  16. // 将物体添加到场景中
  17. scene.add(cube)
  18. // 初始化渲染器
  19. const renderer = new THREE.WebGLRenderer();
  20. // 设置渲染的尺寸大小
  21. renderer.setSize(window.innerWidth, window.innerHeight);
  22. // 将webgl渲染的canvas内容添加到body
  23. document.body.appendChild(renderer.domElement);
  24. // 使用渲染器,通过相机将场景渲染进来
  25. renderer.render(scene, camera);

1.3、轨道控制器查看物体

  1. import * as THREE from "three"
  2. // 导入轨道控制器
  3. import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'
  4. // 1、创建场景
  5. const scene = new THREE.Scene()
  6. // 2、创建相机
  7. const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
  8. // 3、设置相机位置
  9. camera.position.set(0, 0, 10);
  10. scene.add(camera)
  11. // 添加物体
  12. // 创建几何体
  13. const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
  14. // 材质
  15. const cubeMaterial = new THREE.MeshBasicMaterial({color: 0xffff00});
  16. // 根据几何体和材质创建物体
  17. const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
  18. // 将物体添加到场景中
  19. scene.add(cube)
  20. // 初始化渲染器
  21. const renderer = new THREE.WebGLRenderer();
  22. // 设置渲染的尺寸大小
  23. renderer.setSize(window.innerWidth, window.innerHeight);
  24. // 将webgl渲染的canvas内容添加到body
  25. document.body.appendChild(renderer.domElement);
  26. // 使用渲染器,通过相机将场景渲染进来
  27. // renderer.render(scene, camera);
  28. // 创建轨道控制器
  29. const controls = new OrbitControls(camera, renderer.domElement);
  30. function render() {
  31. renderer.render(scene, camera);
  32. // 渲染下一帧的时候就会调用render函数
  33. requestAnimationFrame(render)
  34. }
  35. render();

可以拖动了。

二、three.js辅助设置

2.1、添加坐标轴辅助器

  1. // 添加坐标轴辅助器 5代表轴的线段长度
  2. const axesHelper = new THREE.AxesHelper(5)
  3. scene.add(axesHelper)

红色代表X轴,绿色代表Y轴,蓝色代表Z轴。

2.2、设置物体移动

  1. // 修改物体的位置
  2. // 参数分别为 x,y,z
  3. cube.position.set(5, 2, 0)

当然你也可以使用直接点的形式:

  1. cube.position.x = 5
  2. cube.position.y = 2

小案例:模拟物体从左到右循环运动

  1. function render() {
  2. cube.position.x += 0.01
  3. if (cube.position.x > 5) {
  4. cube.position.x = 0
  5. }
  6. renderer.render(scene, camera);
  7. // 渲染下一帧的时候就会调用render函数
  8. requestAnimationFrame(render)
  9. }

2.3、物体的缩放与旋转

缩放

  1. // 缩放
  2. // 参数 x轴是3倍,y轴是两倍
  3. cube.scale.set(3, 2, 1)

旋转

  1. //旋转
  2. // 参数都为弧度,Math.PI / 4代表绕X轴旋转45度
  3. cube.rotation.set(Math.PI / 4, 0, 0)

小案例:模拟物体从左到右循环运动,并按X轴旋转

  1. function render() {
  2. cube.position.x += 0.01
  3. cube.rotation.x += 0.01
  4. if (cube.position.x > 5) {
  5. cube.position.x = 0
  6. }
  7. renderer.render(scene, camera);
  8. // 渲染下一帧的时候就会调用render函数
  9. requestAnimationFrame(render)
  10. }

2.4、应用requestAnimationFrame

首先,我们的render函数有个默认的参数time,代表每一帧的时间,如果你打印会发现每一帧的时间都不太匀速,比如我们上面这个案例,x轴长度为5,假如我打算1秒运动长度1,匀速就是5秒完成,但打印结果并不是匀速的。

  1. // 匀速
  2. function render(time) {
  3. let t = time / 1000 % 5;
  4. cube.position.x = t * 1
  5. if (cube.position.x > 5) {
  6. cube.position.x = 0
  7. }
  8. renderer.render(scene, camera);
  9. // 渲染下一帧的时候就会调用render函数
  10. requestAnimationFrame(render)
  11. }

2.5、通过Clock跟踪时间处理动画

  1. // 设置时钟
  2. const clock = new THREE.Clock();
  3. function render() {
  4. // 获取时钟运行的总时长
  5. let time = clock.getElapsedTime();
  6. console.log("时钟运行总时长:", time);
  7. let deltaTime = clock.getDelta();
  8. console.log("两次获取时间的间隔时间:", deltaTime)
  9. let t = time % 5;
  10. cube.position.x = t * 1
  11. if (cube.position.x > 5) {
  12. cube.position.x = 0
  13. }
  14. renderer.render(scene, camera);
  15. // 渲染下一帧的时候就会调用render函数
  16. requestAnimationFrame(render)
  17. }

2.6、Gsap动画库基本使用与原理

npm install gsap

动画库的作用就解决了我们上面手动计算处理动画的问题。

  1. // 设置动画
  2. // x轴上移动到5的位置,所花费时间5秒
  3. gsap.to(cube.position, {x: 5, duration: 5, ease: "power1.out"})
  4. // 绕x轴上旋转到360度,所花费时间5秒
  5. gsap.to(cube.rotation, {x: 2 * Math.PI, duration: 5})
  6. function render() {
  7. renderer.render(scene, camera);
  8. // 渲染下一帧的时候就会调用render函数
  9. requestAnimationFrame(render)
  10. }

ease属性(速率):

        power1.out:起始阶段平滑地加速,然后以逐渐减速的方式结束。

        power1.in:起始阶段缓慢加速,然后以较快的速度向目标值靠近。

        power1.inOut:在动画开始和结束时,属性的变化速度较慢,然后在动画的中间阶段达到最快的变化速度。

2.7、Gsap控制动画属性与方法

  1. // 设置动画
  2. // x轴上移动到5的位置,所花费时间5秒
  3. let animate1 = gsap.to(cube.position, {
  4. x: 5,
  5. duration: 5,
  6. ease: "power1.inOut",
  7. repeat: -1, // 设置重复的次数,无限次循环-1
  8. yoyo: true, // 往返运动
  9. delay: 2, // 延迟2秒运动
  10. onStart: () => {
  11. console.log("动画开始")
  12. },
  13. onComplete: () => {
  14. console.log("动画完成")
  15. }
  16. })
  17. // 绕x轴上旋转到360度,所花费时间5秒
  18. gsap.to(cube.rotation, {x: 2 * Math.PI, duration: 5})
  19. // 点击动画,暂停或恢复
  20. window.addEventListener("click", () => {
  21. if(animate1.isActive()) {
  22. animate1.pause(); // 暂停
  23. } else {
  24. animate1.resume(); // 恢复运动
  25. }
  26. })

2.8、根据尺寸变化实现自适应画面

阻尼效果

  1. // 设置控制器阻尼,让控制器更有真实效果,必须在动画循环里调用update()
  2. controls.enableDamping = true;
  3. function render() {
  4. controls.update();
  5. renderer.render(scene, camera);
  6. // 渲染下一帧的时候就会调用render函数
  7. requestAnimationFrame(render)
  8. }

自适应画面

  1. // 监听画面变化,更新渲染画面
  2. window.addEventListener("resize", () => {
  3. // 更新摄像头
  4. camera.aspect = window.innerWidth / window.innerHeight;
  5. // 更新摄像机的投影矩阵
  6. camera.updateProjectMatrix();
  7. // 在更新渲染器
  8. renderer.setSize(window.innerWidth, window.innerHeight)
  9. // 设置渲染器的像素比
  10. renderer.setPixelRatio(window.devicePixelRatio);
  11. })

尽管你更改分辨率,这段代码都会保持画面原样。

2.9、调用js接口控制画布全屏和退出全屏

  1. // 双击控制屏幕进入全屏,退出全屏
  2. window.addEventListener("dblclick", () => {
  3. const fullScreenElement = document.fullscreenElement; // 页面是否处于全屏
  4. if (!fullScreenElement){
  5. renderer.domElement.requestFullscreen(); // 全屏
  6. } else {
  7. document.exitFullscreen(); // 退出全屏
  8. }
  9. })

2.10、应用图形用户界面更改变量

很多时候我们调试3D图像很麻烦,普遍都是改完代码然后看页面效果,而dat.gui就大大简化了我们的操作问题。

npm install -save dat.gui
  1. // 导入dat.gui
  2. import * as dat from 'dat.gui'
  3. const gui = new dat.GUI();
  4. gui.add(cube.position, "x").min(0).max(5).name("移动X轴坐标").onChange((value) => {
  5. console.log("值被修改:", value)
  6. }).onFinishChange((value) => {
  7. console.log("完全停下来触发:", value)
  8. })

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/98108
推荐阅读
相关标签
  

闽ICP备14008679号