在 Three.js 中,更新场景是创建动态和交互式三维应用的关键。通过不断更新场景中的对象、摄像机、光源等,可以实现动画效果、交互反应和视觉变化。本文将详细介绍如何在 Three.js 中更新场景,包括更新位置、旋转、缩放,以及处理动画和响应用户输入。
在 Three.js 中,更新场景通常涉及以下几个方面:
AnimationMixer
更新模型的动画。requestAnimationFrame
实现流畅的更新。在开始之前,我们先创建一个基本的 Three.js 场景,包含一个立方体和一个摄像机。
确保在你的 HTML 文件中引入 Three.js:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js 更新场景示例</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
在 <script>
标签中,设置基本的 Three.js 场景、摄像机和渲染器:
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
我们可以通过修改对象的 position
属性来更新其位置。以下是一个简单的例子,使立方体在 x 轴上移动:
function updatePosition() {
cube.position.x += 0.01; // 每帧向右移动
if (cube.position.x > 5) {
cube.position.x = -5; // 循环移动
}
}
可以通过修改对象的 rotation
属性来旋转对象。以下是使立方体旋转的代码:
function updateRotation() {
cube.rotation.x += 0.01; // 绕 x 轴旋转
cube.rotation.y += 0.01; // 绕 y 轴旋转
}
类似地,可以通过 scale
属性更新对象的缩放:
function updateScale() {
cube.scale.x = Math.sin(Date.now() * 0.001) + 1; // 使立方体在 x 轴上动态缩放
}
将所有更新逻辑结合在一起,通过 requestAnimationFrame
实现渲染循环:
function animate() {
requestAnimationFrame(animate);
updatePosition();
updateRotation();
updateScale();
renderer.render(scene, camera);
}
animate();
为了增强场景的视觉效果,可以添加光源和启用阴影。
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); // 环境光
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1); // 平行光
directionalLight.position.set(5, 5, 5).normalize();
scene.add(directionalLight);
renderer.shadowMap.enabled = true;
cube.castShadow = true;
directionalLight.castShadow = true;
如果模型包含动画,可以使用 AnimationMixer
来更新动画。以下是一个使用 GLTFLoader 加载模型并播放动画的示例:
const loader = new THREE.GLTFLoader();
let mixer;
loader.load('path/to/model.glb', (gltf) => {
scene.add(gltf.scene);
mixer = new THREE.AnimationMixer(gltf.scene);
gltf.animations.forEach((clip) => {
mixer.clipAction(clip).play();
});
});
在渲染循环中更新动画:
function animate() {
requestAnimationFrame(animate);
updatePosition();
updateRotation();
updateScale();
if (mixer) mixer.update(0.01); // 更新动画
renderer.render(scene, camera);
}
通过监听用户输入(例如鼠标、键盘等),可以动态更新场景。以下是一个响应键盘输入以控制立方体颜色的示例:
window.addEventListener('keydown', (event) => {
if (event.key === 'r') {
cube.material.color.set(0xff0000); // 按 R 键时改变颜色
}
if (event.key === 'g') {
cube.material.color.set(0x00ff00); // 按 G 键时改变颜色
}
if (event.key === 'b') {
cube.material.color.set(0x0000ff); // 按 B 键时改变颜色
}
});
将所有内容整合,得到完整的 HTML 文件:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js 更新场景示例</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/examples/js/loaders/GLTFLoader.js"></script>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
<script>
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
function updatePosition() {
cube.position.x += 0.01; // 每帧向右移动
if (cube.position.x > 5) {
cube.position.x = -5; // 循环移动
}
}
function updateRotation() {
cube.rotation.x += 0.01; // 绕 x 轴旋转
cube.rotation.y += 0.01; // 绕 y 轴旋转
}
function updateScale() {
cube.scale.x = Math.sin(Date.now() * 0.001) + 1; // 使立方体在 x 轴上动态缩放
}
function animate() {
requestAnimationFrame(animate);
updatePosition();
updateRotation();
updateScale();
renderer.render(scene, camera);
}
animate();
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
// 添加光源
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 5, 5).normalize();
scene.add(directionalLight);
// 监听键盘事件
window.addEventListener('keydown', (event) => {
if (event.key === 'r') {
cube.material.color.set(0xff0000); // 改变颜色
}
if (event.key === 'g') {
cube.material.color.set(0x00ff00);
}
if (event.key === 'b') {
cube.material.color.set(0x0000ff);
}
});
</script>
</body>
</
html>
在本文中,我们详细探讨了如何在 Three.js 中更新场景,包括基本的对象变换、处理动画和用户输入,以及创建流畅的渲染循环。这些更新机制使得开发者能够创建生动的三维应用,提升用户体验。希望本博客能帮助你更好地理解 Three.js 的使用!如果有任何问题或建议,欢迎在评论区留言讨论!