引言
本技术文档将详细介绍如何使用 Three.js 在 Web 环境中加载和控制 GLTF 3D 模型,并为模型设置多个动画状态。本文将包括从初始化 Three.js 场景、加载 GLTF 模型、处理动画混合器和切换动画状态到实现用户界面的步骤。该文档特别适合开发交互式 Web 应用、3D 模型查看器或简单的游戏等场景。
关键概念概述
1. Three.js 简介
Three.js 是一个基于 JavaScript 的 3D 图形库,提供了一系列强大且易用的 API 来创建和操控 3D 场景。Three.js 封装了 WebGL 的复杂性,使开发者能够更轻松地实现 3D 渲染。它支持各种几何体、材质、光源、阴影效果等,并且与 GLTF 模型兼容。
2. GLTF(GL 传输格式)简介
GLTF 是一种开放、通用的 3D 文件格式,用于高效传输和加载 3D 模型及其相关资源(如纹理、动画等)。Three.js 提供了对 GLTF 的原生支持,能够方便地加载和渲染这些 3D 模型,并支持它们的动画播放。
实现步骤
1. 准备工作与环境搭建
在项目中使用 Three.js 进行 3D 渲染时,首先需要确保引入了相关的脚本库。你可以直接使用 CDN 引入,也可以通过 npm 安装。为了简单起见,我们将直接通过 CDN 引入库文件。
xml
html
复制代码
<script src="https://cdn.jsdelivr.net/npm/three@0.137.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.137.0/examples/js/loaders/GLTFLoader.js"></script>
在项目中还需要准备一个简单的 HTML 页面,在这个页面中,Three.js 将加载并渲染 3D 模型。
xml
html
复制代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js GLTF 模型与动画</title>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
<div id="controls"></div>
<script src="three.min.js"></script>
<script src="GLTFLoader.js"></script>
</body>
</html>
2. 初始化 Three.js 场景
在 Web 页面中,首先要初始化 Three.js 场景,包括创建场景、相机和渲染器。以下代码演示了如何初始化一个基本的 Three.js 场景。
ini
javascript
复制代码
let scene, camera, renderer;
function init() {
// 创建场景
scene = new THREE.Scene();
scene.background = new THREE.Color(0xe0e0e0); // 设置场景背景颜色
// 创建相机
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.25, 100);
camera.position.set(-5, 3, 10); // 设置相机位置
camera.lookAt(new THREE.Vector3(0, 2, 0)); // 设置相机目标位置
// 创建 WebGL 渲染器
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 添加光源
const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444);
hemiLight.position.set(0, 20, 0);
scene.add(hemiLight);
const dirLight = new THREE.DirectionalLight(0xffffff);
dirLight.position.set(0, 20, 10);
scene.add(dirLight);
}
3. 加载 GLTF 模型
接下来,我们使用 GLTFLoader 来加载一个 GLTF 模型文件。Three.js 提供了 GLTFLoader 来解析和加载 .gltf 或 .glb 格式的 3D 模型文件。
ini
javascript
复制代码
const loader = new THREE.GLTFLoader();
loader.load('模型文件URL', function (gltf) {
const model = gltf.scene;
scene.add(model); // 将模型添加到场景中
const mixer = new THREE.AnimationMixer(model); // 创建动画混合器
const animations = gltf.animations; // 获取模型的所有动画
const actions = {};
// 遍历动画并创建动作
animations.forEach(clip => {
const action = mixer.clipAction(clip);
actions[clip.name] = action; // 存储每个动作
});
// 设置初始状态并播放动画
actions['Idle'].play();
});
4. 设置动画状态切换
为了能够切换动画状态,我们需要创建一个函数,用来控制模型的不同动画状态的播放。通过调用 AnimationMixer 的 clipAction 方法,我们可以获取模型的动画动作,并通过 fadeIn 和 fadeOut 来实现平滑切换。
scss
javascript
复制代码
let activeAction, previousAction;
function setState(state) {
previousAction = activeAction;
activeAction = actions[state];
if (previousAction !== activeAction) {
if (previousAction) {
previousAction.fadeOut(0.5); // 旧动作淡出
}
activeAction.reset().fadeIn(0.5).play(); // 新动作淡入
}
}
我们可以通过按钮或其他交互方式来调用 setState 函数。例如,可以在页面中添加几个按钮,让用户选择不同的动画状态:
ini
html
复制代码
<div class="controls">
<button onclick="setState('Idle')">Idle</button>
<button onclick="setState('Walking')">Walking</button>
<button onclick="setState('Running')">Running</button>
</div>
5. 响应窗口大小调整
为了确保页面在窗口大小调整时保持正确的比例和布局,我们可以添加一个事件监听器,当窗口大小发生变化时自动调整相机的纵横比并重新设置渲染器的尺寸。
javascript
javascript
复制代码
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
6. 动画更新循环
最后,为了确保动画正常运行,我们需要在 requestAnimationFrame 中更新场景和动画混合器。这个函数将被循环调用以更新动画帧。
scss
javascript
复制代码
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta(); // 获取时间间隔
if (mixer) mixer.update(delta); // 更新动画
renderer.render(scene, camera); // 渲染场景
}
7. 完整代码示例
xml
html
复制代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js GLTF Model with Animation States</title>
<style>
body { margin: 0; }
canvas { display: block; }
.controls {
position: absolute;
top: 10px;
left: 10px;
z-index: 10;
}
.controls button {
margin: 5px;
padding: 10px;
background-color: #ccc;
border: none;
cursor: pointer;
}
</style>
</head>
<body>
<div class="controls">
<button onclick="setState('Idle')">Idle</button>
<button onclick="setState('Walking')">Walking</button>
<button onclick="setState('Running')">Running</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/three@0.137.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.137.0/examples/js/loaders/GLTFLoader.js"></script>
<script>
let scene, camera, renderer, model, mixer, actions = {}, activeAction, previousAction;
const clock = new THREE.Clock();
function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color(0xe0e0e0);
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.25, 100);
camera.position.set(-5, 3, 10);
camera.lookAt(new THREE.Vector3(0, 2, 0));
const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444);
hemiLight.position.set(0, 20, 0);
scene.add(hemiLight);
const dirLight = new THREE.DirectionalLight(0xffffff);
dirLight.position.set(0, 20, 10);
scene.add(dirLight);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const loader = new THREE.GLTFLoader();
loader.load('https://threejs.org/examples/models/gltf/RobotExpressive/RobotExpressive.glb', function (gltf) {
model = gltf.scene;
scene.add(model);
mixer = new THREE.AnimationMixer(model);
gltf.animations.forEach((clip) => {
const action = mixer.clipAction(clip);
actions[clip.name] = action;
});
setState('Idle');
animate();
});
}
function setState(state) {
if (actions[state]) {
previousAction = activeAction;
activeAction = actions[state];
if (previousAction !== activeAction) {
if (previousAction) {
previousAction.fadeOut(0.5);
}
activeAction.reset().fadeIn(0.5).play();
}
}
}
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
if (mixer) mixer.update(delta);
renderer.render(scene, camera);
}
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
init();
</script>
</body>
</html>
结论
通过这篇文档,你可以了解到如何使用 Three.js 加载并控制一个带有多个动画状态的 GLTF 模型。我们详细讲解了如何初始化场景、加载模型、创建动画混合器并切换动画状态。
链接:https://juejin.cn/post/7413228844403048489
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
2. 分享目的仅供大家学习和交流,请不要用于商业用途!
3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员!
8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载
声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性
GLB下载网 - GLB/GLTF模型与格式资源免费下载,支持在线浏览与转换 » Three.js GLTF/GLB 模型与动画状态控制技术文档
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载要提取码
- 分享过期和重复下载怎么办
- 模型和平台不兼容怎么办