在 Three.js 中,我们通常会加载带有动画的模型,这些动画可能包含多个部件的运动(如车门的开闭、轮胎的旋转等)。为了使模型中的动画更加生动且易于控制,我们可以借助 GSAP(GreenSock Animation Platform)库,直接控制模型的各个部分或整个动画序列。本文将介绍两种常见的应用场景:一是通过 GSAP 控制模型中某个组件的动画,二是控制整个模型的动画播放。
模型设计师与程序员的协作
在 3D 项目开发中,模型设计师和程序员需要紧密合作。设计师有时会将动画直接嵌入到模型中,而有时他们仅提供动画的基本框架,让程序员来控制动画的细节。这种做法通常取决于项目需求和开发进度。
-
设计师嵌入动画:设计师可以在模型制作时就将动画直接加入(例如,车门开关、人物动作等)。这些动画会被打包进模型文件中,程序员只需通过 Three.js 的 AnimationMixer 来控制动画的播放。
-
程序员控制动画:如果设计师没有在模型中预设动画,或者需要程序员根据用户交互来控制动画,程序员可以通过 GSAP 或 Three.js 的动画系统,直接控制模型的各个部件(如门、车轮等)的旋转、平移等动画效果。
无论哪种方式,程序员都可以利用 GSAP 来进一步优化和控制动画的播放,增强用户体验。
1. 使用 GSAP 控制模型中的元件动画
有时我们不需要播放整个模型的动画序列,而是希望单独控制模型中的某个部件(例如车门)的动画。在这种情况下,我们可以直接通过 GSAP 来控制目标元件的属性变化,通常是旋转、平移等。
示例:控制车门的开关
假设我们有一个包含多个车门动画的模型,但我们只希望控制其中一个车门的开关。通过 GSAP,我们可以控制车门的旋转或平移,以实现开门和关门的动画效果。
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import gsap from 'gsap';
// 初始化场景、相机和渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 2, 5);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
// 添加环境光
const light = new THREE.AmbientLight(0xffffff, 1);
scene.add(light);
// 加载 GLTF 模型
const loader = new GLTFLoader();
let car; // 存储整个车模型
let doorLF; // 左前门模型
let isDoorLFOpen = false; // 车门开关状态
loader.load(
"path/to/your/car_model.glb", // 替换为你的模型路径
(gltf) => {
car = gltf.scene;
scene.add(car);
// 假设左前门的模型名字为 "Door_LF"(根据你的模型结构)
doorLF = car.getObjectByName("Door_LF");
// 确保门处于关闭状态
doorLF.rotation.y = 0;
// 设置默认动画状态
doorLF.visible = true;
},
undefined,
(error) => {
console.error("加载模型失败", error);
}
);
// 渲染循环
function animate() {
requestAnimationFrame(animate);
controls.update(); // 更新控制器
renderer.render(scene, camera);
}
animate();
// 按钮事件控制
document.getElementById("toggleLF").addEventListener("click", () => {
if (!doorLF) return; // 如果门尚未加载,跳过
if (isDoorLFOpen) {
// 使用 GSAP 反向动画打开车门
gsap.to(doorLF.rotation, {
y: 0, // 关门,y轴旋转回原始位置
duration: 1,
ease: "power2.out"
});
} else {
// 使用 GSAP 动画打开车门
gsap.to(doorLF.rotation, {
y: Math.PI / 2, // 打开门,y轴旋转 90 度
duration: 1,
ease: "power2.out"
});
}
// 切换车门状态
isDoorLFOpen = !isDoorLFOpen;
});
关键点解析
-
获取目标元件:
使用car.getObjectByName("Door_LF")获取车门的 3D 对象。你需要根据你的模型实际结构修改Door_LF为你想控制的部件名称。 -
GSAP 动画控制:
gsap.to(doorLF.rotation, { y: Math.PI / 2, duration: 1, ease: "power2.out" }):控制车门沿 Y 轴旋转 90 度,以模拟车门打开。gsap.to(doorLF.rotation, { y: 0, duration: 1, ease: "power2.out" }):将车门旋转回原始位置,模拟车门关闭。
-
控制状态:
使用布尔变量isDoorLFOpen来跟踪车门的开关状态,每次点击按钮时反转该状态,并触发动画。
2. 控制整个模型中的动画
有时我们需要控制整个模型的动画序列,比如车门的开闭、车轮的转动等,通常这些动画已经预设在模型文件中。我们可以使用 AnimationMixer 来播放这些动画,但如果你想通过 GSAP 来控制这些动画的播放状态、速率或进度,也完全可以实现。
示例:控制整个车门开关的动画
假设模型中已经包含了车门开关的动画序列,我们希望通过 GSAP 来控制整个动画的播放、暂停或进度。
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
// 初始化场景和渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 2, 5);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 加载 GLTF 模型
const loader = new GLTFLoader();
let mixer; // 动画混合器
loader.load(
"path/to/your/car_model.glb", // 替换为你的模型路径
(gltf) => {
const model = gltf.scene;
scene.add(model);
// 创建 AnimationMixer
mixer = new THREE.AnimationMixer(model);
// 获取完整动画片段
const fullAnimationClip = gltf.animations[0]; // 假设第一个动画是车门开闭
const action = mixer.clipAction(fullAnimationClip);
// 控制动画的播放
action.play(); // 播放动画
// 控制动画的暂停
action.paused = true; // 暂停动画
// 修改动画的播放速度
action.timeScale = 2; // 动画加速
},
undefined,
(error) => {
console.error("加载模型失败", error);
}
);
// 渲染循环
function animate() {
requestAnimationFrame(animate);
if (mixer) mixer.update(0.01); // 更新动画混合器
renderer.render(scene, camera);
}
animate();
关键点解析
-
AnimationMixer控制动画:
使用 AnimationMixer 来管理和控制模型的动画。通过 clipAction 获取动画,并使用 action.play() 开始播放,或者 action.paused = true 来暂停动画。 -
GSAP 控制动画进度和速率:
- 通过
gsap.to()可以控制整个动画的进度,比如改变动画播放速率timeScale或者设置动画的播放时间。
- 通过
-
灵活控制动画:
使用 GSAP 可以更加精细地控制动画效果,包括速度、延迟、反向播放等,增强用户体验。
小结
无论是直接使用 Three.js 内置的动画系统,还是结合 GSAP 来实现更加精细的动画控制,模型动画的实现都需要依赖设计师和程序员的协作。通过合理的接口设计,程序员可以在不干扰设计师模型的基础上,实现更多的交互效果和控制方式。
希望本文的示例能帮助你更好地理解如何在 Three.js 中使用 GSAP 控制动画。如果你有其他问题,欢迎随时讨论!
订阅 FreeMac
每周精选:Mac 高效技巧、免费替代付费软件、开发者工具推荐。用对你的 MacBook,省钱 + 提效。