创建3D贺卡的案例
- 加载模型后通过回调函数来设置模型
- 获取模型的场景
1
const model = gltf.scene
- 模型的缩放大小
1
model.scale.set(x,y,z)
- 遍历模型 这里能拿到模型的部件
- 注:Mesh是由几何体和材质组成的网格,而网格才能渲染在屏幕上
1
2
3
4
5
6model.traverse((child) => {
child.Mesh // 获取部件的网格
child.name // 获取部件的名称,可以用来控制对应部件要展示什么效果
child.visible = true; // 设置部件是否渲染,false不渲染
})
- 注:Mesh是由几何体和材质组成的网格,而网格才能渲染在屏幕上
- 把模型添加到场景中 最重要
1
scene.add(model)
基础语法
设置模型/网格在场景的位置(position)
1 | mesh.position.set(x,y,z) |
设置物体旋转(rotation)
- 表示的是绕x/y/z轴旋转的弧度
1
2
3mesh.rotation.set(x,y,z)
mesh.rotation.x = x
mesh.rotation = new THREE.Vector3(x,y,z)
设置模型/网格相对于原来位置的移动距离(translate) – 用法同position一样
直射光 — 场景中物理材质一定要有,模拟阳光
- 创建直射光并添加到场景中
1
2const light = new THREE.DirectionalLight(灯光颜色, 强度默认1)
scene.add(light)
点光源
作用类似于让屋子亮灯,屋子开了个门,门口会投射灯光
- 添加点光源
1
const pointlight = new THREE.PointLight(光源的颜色, 光的强度)
- 适当调整位置
- 设置灯光投射阴影
1
pointlight.castShadow = true
- 设置渲染器允许光源有阴影
1
renderer.shadowMap.enabled = true
- 在模型中设置允许接受阴影和投射阴影并将光源添加到场景中
1
2
3
4
5if (child.Mesh) {
child.receiveShadow = true
child.castShadow = true
}
scene.add(pointlight)
创建一个点光源组
这是一个由球转载点光源的组
- 创建一个光源组并调正光源组的位置
1
2const pointLightGroup = new THREE.Group()
pointLightGroup.position.set(2, 4, 2) - 设置球体的半径, 空数组, 并通过循环产生n个球体光源
1
2
3
4
5
6
7
8
9
10
11
12
13const radius = 3
let pointLightArr = []
for (let i = 0; i< n; i++) {
const sphereGeometry = new THREE.SphereGeometry(0.2, 32, 32) // 创建球体
const sphereMaterial = new THREE.MeshStandardMaterial({ // 创建球体的材质 --- 物理材质(会通过周围的灯光映射颜色)
color: 0xffffff, // 球体的颜色
emissive: 0xffffff, // 光源的颜色
emissiveIntensity: 10 // 光源的强度
})
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial) // 创建网格
const pointLight = new THREE.PointLight(0xffffff, 10) // 创建点光源
pointLightArr.push(sphere) // 创建好的添加到数组中
} - 设置球体的位置, 在球体中添加点光源,然后将将球体添加到组中
1
2
3
4
5
6
7sphere.position.set(
radius * Math.cos((i * 2 * Math.PI) /3), // x
Math.cos((i * 2 * Math.PI) / 3), // y
radius * Math.sin((i * 2 * Math.PI) /3), // z
)
sphere.add(pointLight)
pointLightGroup.add(sphere) - 在场景中添加点光源组
1
scene.add(pointLightGroup)
使用补间动画让光源组旋转,上下移动
1 | let options = { angle: 0} // 从零开始 |
水面
- 引用水的模型包
1
import { Water} from "three/examples/jsm/objects/Water2"
- 创建一个圆的平面
1
const waterGeometry = new THREE.CircleGeometry(半径,分段默认32)
- 创建水面
1
2
3
4
5
6
7const water = new Water(waterGeometry, {
textureWidth: 1024, // 画布的宽度
textureHeight: 1024, // 画布的高度
color: 0xededed, // 水面颜色
flowDirection: new THREE.Vector2(1,1), // 水流动方向
scale:100, // 水波方位
}) - 由于水面创造出来是垂直于模型,需旋转90度, 然后添加到场景中
1
2water.rotation.x = -Math.PI / 2
scene.add(water)
色调映射
…renderer.xxx
相机位置与文字切屏
- 使用补间动画移动相机
- 调用gasp的timeline()创建两个变量
- 封装一个相机移动函数,并使用这两个变量分别控制相机要移动的位置和聚焦,并设置xyz,duration和ease
- 写一个对象数组,其中包括文本信息和回调函数,回调函数中调用相机移动函数,并给予坐标
- 监听鼠标滚轮事件判断滚轮是否向下滚动,
- 是,变量+1并判断只有当变量小于对象数组的长度-1时,才加一,否则为0;
- 否,直接调用对象数组的第变量对象的回调函数。
- 建议增加防抖操作,防抖变量为true返回,鼠标滚动时,延时一定时间让防抖变量为false
- 最后在页面中通过遍历来展示文本,在最外层则通过修改 translate3d 来控制滚轮动时文本页跟着变。
1
:style="{transform: 'translate3d(0, ${-index*100}vh, 0)'}"
创建漫天星星
- 通过InstancedMesh来创建100个以上的球的实例
- 随机分配到天上
- `创建开始位置和结束位置的空数组
- 通过for循环,获取随机的x,y,z 并添加到开始数组中
- 创建一个矩阵,并设置位置,然后设置实例的矩阵
- 添加到场景中,
- 使用贝塞尔曲线话爱心路径
- 根据路径获取点getPoint
- 通过for循环获取曲线的每一个点,并添加到结束数组,如果图形太大可以给x,y乘以一个小数
- 创建爱心动画
- 定义一个参数,设置时间为0
- 然后使用补间动画从0执行到1,更新时是实时获取开始数组的当前位置+ (结束位置-开始位置)* 参数的时间
- 创建一个矩阵,并设置位置,然后设置实例的矩阵
- 设置实例的矩阵需要更新
- 定义一个参数,设置时间为0
- 创建复原的函数
- 与爱心动画一样,只需要把开始数组替换为结束数组,结束数组替换为开始数据即可
- 在对象数组中需要呈现的回调函数中调用爱心动画函数
- 在监听事件中,当变量要设置为0 时添加复原函数