1.Three三要素相机,场景,几何体初始化
1.引入Three.js
import * as THREE from "three";
2.创建场景
// 1.创建一个场景 const scene = new THREE.Scene();
3.初始化一个相机
// 1.创建一个相机 const camera = new THREE.PerspectiveCamera(75, window, innerWidth / window.innerHeight, 0.1, 1000); // 角度,长宽比.可视近端,可视远端 // 2.相机的位置设置(x,y,z)坐标位置 camera.position.set(0,0,100); // 3.相机放在场景当中 scene.add(camera);
4.初始化一个几何体
// 1.场景添加物体 // 1.1 创建 长宽高 值为1 的立方体 几何 const geometry = new THREE.BoxGeometry( 10, 10, 10 ); // 1.2 给几何体设定材质 const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} ); // 1.3 根据几何体和材质创建物体 const cube = new THREE.Mesh( geometry, material ); // 1.4 物体添加到场景中 scene.add( cube );
5.初始化一个渲染器, 用来通过相机把画面渲染到
// 7.初始化渲染器 const renderer = new THREE.WebGL1Renderer(); // 8.设置渲染的尺寸大小 renderer.setSize(window.innerWidth,window.innerHeight); // 9.将webgl渲染的canvas内容添加到body上 document.body.appendChild(renderer.domElement); // 10.使用渲染器,通过相机将场景渲染出来 // renderer.render(scene,camera);
6.创建渲染函数,每一帧渲染,
// 创建渲染函数,每一帧渲染 function render(){ renderer.render(scene,camera); // 请求动画帧,JavaScript会请求上次函数执行的结果继续执行这个函数 requestAnimationFrame(render) } render()
2.几何体的移动,旋转,缩放
移动
// 修改物体的位置 cube.position.set(5,0,0) cube.position.x = 5 cube.position.y = 5 cube.position.z = 5
缩放
// 物体的缩放 cube.scale.set(3,2,1) cube.scale.x= 5 cube.scale.y = 2.5 cube.scale.z = 5
旋转
// 物体的旋转 cube.rotation.set(40,0,0,"XYZ")
3. Group概念 容器
引入概念
如果你要实现一个机器人在跑步,那么机器人的头、四肢、躯干等都是要整体移动的,group可以将一系列的mesh模型组成一个整体,这样就可以实现整体移动了。
// 创建group容器 const group = new THREE.Group() // 创建每一个物体 const cube1 = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshBasicMaterial({ color: 0xfff000 })) const cube2 = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshBasicMaterial({ color: 0xff0000 })) const cube3 = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshBasicMaterial({ color: 0xf00ff0 })) // 将每一个物体添加到group容器当中 group.add(cube1,cube2,cube3) // 将容器添加到场景当中 scene.add(group) // 所以我们只需要移动group 就可以实现容器里面每个物体的移动,缩放,旋转 group.position.set(2,0,0) group.scale.set(2,2,2) group.rotation.set(Math/2,0,0,"XYZ")
4. GSAP动画库
4.1 什么是“GSAP”?
GreenSock 动画平台 (GSAP) 是一套行业知名的工具套件,用于超过 1100 万个网站,其中包括超过 50% 的获奖网站!你可以在任何框架中使用GSAP来制作 JavaScript*可以触及的几乎所有东西。 *无论您是想为 UI、SVG、Three 还是 React 组件制作动画.js - GSAP 都能满足您的需求。
核心库包含创建超快、跨浏览器友好动画所需的一切。这就是我们将在本文中逐步介绍的内容。
除了核心,还有各种各样的插件。您无需学习它们即可开始使用** ,但它们可以帮助解决特定的动画挑战,例如基于滚动的动画、可拖动的交互、变形等。
4.2 使用
下载:
npm i gasp
引入:
// 导入动画库 import { gsap } from 'gsap'
使用:
// 设置动画 // 哪个元素(物体),移动哪个轴 多少距离,所用时间 间隔多长时间 var animation = gsap.to(cube.position, { // x轴移动10距离 x: 5, // 完成动画所需时间 duration: 3, // 往返运动 yoyo: true, // 延迟开启动画 单位S delay: 3, // 动画移动速率 // ease: "elastic.out(1, 0.3)", // 动画重复次数,无限次:-1 repeat: -1, // 动画完成之后的回调 onComplete: () => { console.log("动画完成"); }, // 动画开始之后的回调 onStart: () => { console.log("动画开始"); } }) gsap.to(cube.rotation, { x: 180, duration: 3 }) // 点击停止动画 window.addEventListener('dblclick', () => { console.log(animation); if (animation.isActive()) { // 暂停动画 animation.pause(); } else { // 恢复动画 animation.resume() } })
5.二维平面PlaneGeometry
1.PlaneGeometry几何体介绍
PlaneGeometry可以用来创建非常简单的矩形,创建这种几何体非常简单,
const geom = new THREE.PlaneGeometry(width, height, widthSegments, heightSegments)
按照如上语句便可以创建
建一个简单的二维矩形平面,接下来介绍一下它的常用属性
属性 | 必须 | 描述 |
width | 是 | 该属性指定矩形的宽度 |
height | 是 | 该属性指定矩形的高度 |
widthSegments | 否 | 该属性指定矩形的宽度应该分成几段 |
heightSegments | 否 | 该属性指定矩形的高度应该分成几段 |
- 通过width属性调整平面的宽度
- 通过height属性调整平面的高度
- 通过widthSegments属性调整平面宽度分的段数
- 通过heightSegments属性调整平面高度分的段数>
6. 轨道控制器
初始化镜头轨道控制器 OrbitControls ,通过它可以对三维场景用鼠标 🖱 进行缩放、平移、旋转等操作,本质上改变的不是场景,而是相机的位置参数。可以选择通过设置 controls.enableDamping 为 true 来开启控制器的移动惯性,这样在使用鼠标交互过程中就会感觉更加流畅和逼真。
第一步:
//导入控制器 import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
第二步:
// 实例化控制器 const controls = new OrbitControls(camera, renderer.domElement); // 阻尼开启 controls.enableDamping = true;
7.TextGeometry文本几何体
TextGeometry文本几何体介绍
TextGeometry可以用来创建三维文本。其实是通过指定字体创建字符,然后像拉伸几何体那样把文字拉伸,继而得到三维文本。创建TextGeometry文本几何体有很多参数与ExtrudeGeometry几何体一样,具体如下:
属性 | 必须 | 描述 |
size | 否 | 该属性指定文本大小,默认值是100 |
height | 否 | 该属性指定文本可以厚度,默认值是50 |
font | 否 | 该属性指定文本的字体,是一个THREE.Font对象 |
bevelEnabled | 否 | 该属性指定文本拉伸时是否启用斜角,默认false |
bevelThickness | 否 | 该属性指定文本拉伸体斜角厚度,默认值是10 |
bevelSize | 否 | 该属性指定文本拉伸体斜角的高度。默认值是8 |
bevelSegments | 否 | 该属性指定文本拉伸体斜角的分段数,段数越多斜角越光滑,默认值是3 |
curveSegments | 否 | 该属性指定文本拉伸时拉伸曲线的分段数,段数越多曲线越光滑,默认值是4 |
TextGeometry文本几何体使用
字体文件引入
示例中使用的是helvetiker字体,通过文件 helvetiker_regular.typeface.js导入字体,将字体文件helvetiker_regular.typeface.js 放在public/font目录下,字体文件可以在这里下载helvetiker_regular.typeface.js引入过程如下:
const publicPath = process.env.BASE_URL
const textLoader = new THREE.FontLoader() //导入字体 textLoader.load( `${publicPath}font/helvetiker_regular.typeface.js`, font => { // 这里可以获取到font就是创建文本几何体需要的字体 })
3D字体对象的创建
// 创建几何体 const geometry = new TextGeometry( 'Hello three.js!', { font: font, size: 80, height: 5, curveSegments: 12, bevelEnabled: true, bevelThickness: 10, bevelSize: 8, bevelSegments: 5 } ); // 创建材质 const meshMaterial = new THREE.MeshStandardMaterial({ color: 0xeeffff }) // 创建文字网格对象 this.mesh = new THREE.Mesh(geometry, meshMaterial) // 网格对象添加到场景中 scene.add(this.mesh)
8. 阴影
阴影的基本使用
- 材质要满足能够对光照有反应
- 设置渲染器开启阴影的计算 renderer.shadowMap.enabled = true;
- 设置光照投射阴影 directionalLight.castShadow = true;
- 设置物体投射阴影 sphere.castShadow = true;
- 设置物体接收阴影 plane.receiveShadow = true;
只有三种光可以支持阴影
- PointLight 点光源
- DirectionalLight 方向光
- SpotLight 聚光灯
1.设置渲染器开启阴影的计算
// 告诉我们的渲染器处理阴影映射 renderer.shadowMap.enabled = true
2.设置物体投射阴影
// 设置物体投射阴影 sphere.castShadow = true;
3.设置物体接收阴影
// 设置物体接收阴影 plane.receiveShadow = true;
4.设置光照投射阴影
// 设置光照投射阴影 directionalLight.castShadow = true;
优化阴影
设置阴影贴图的分辨率
// 设置阴影贴图的分辨率 -- 提高流畅度 directionalLight.shadow.mapSize.set(4096, 4096);
定向光摄像机助手
// 创建定向光相机助手 const directionalLightHelper = new THREE.CameraHelper(directionalLight.shadow.camera); scene.add(directionalLightHelper)
关闭定向光摄像机助手
directionalLightHelper.visible = false
修改物体距离光相机的距离
// 修改定向光相机 距离物体的距离 directionalLight.shadow.camera.near = 0.5; // 光所到达的最远距离 directionalLight.shadow.camera.far = 16; // 这下面四个值的正数一定要相等且对称 directionalLight.shadow.camera.top = 2; directionalLight.shadow.camera.bottom = -2; directionalLight.shadow.camera.left = -2; directionalLight.shadow.camera.right = 2;
设置阴影贴图模糊度
// 设置阴影贴图模糊度 directionalLight.shadow.radius = 20;
设置阴影贴图的类型 这里采用的是PCF软阴影(边缘更好看-更丝滑)
// 设置阴影贴图的类型 这里采用的是PCF软阴影 renderer.shadowMap.type = THREE.PCFShadowMap
聚光灯-SpotLight
// 环境光 const light = new THREE.AmbientLight(0xffffff, 0.5); // soft white light scene.add(light); //直线光源 const spotLight = new THREE.SpotLight(0xffffff, 1); spotLight.position.set(5, 5, 5); spotLight.castShadow = true; spotLight.intensity = 2; // 添加光相机助手 const spotLightHelper = new THREE.CameraHelper(spotLight.shadow.camera) scene.add(spotLightHelper)
// 设置阴影贴图模糊度 // spotLight.shadow.radius = 20; // 设置阴影贴图的分辨率 spotLight.shadow.mapSize.set(1024, 1024); // console.log(directionalLight.shadow); spotLight.target = sphere; // 角度 spotLight.angle = Math.PI / 6; // 距离 spotLight.distance = 0; // 明暗交界处 spotLight.penumbra = 0; // 光的强弱 spotLight.decay = 0; scene.add(spotLight); gui.add(sphere.position, "x").min(-5).max(5).step(0.1); gui .add(spotLight, "angle") .min(0) .max(Math.PI / 2) .step(0.01) .name('角度'); gui.add(spotLight, "distance").min(0).max(10).step(0.01).name('距离'); gui.add(spotLight, "penumbra").min(0).max(1).step(0.01).name('明暗交界处'); gui.add(spotLight, "decay").min(0).max(5).step(0.01).name('光的强弱');