第七章 Three.js 动画与交互

发布于:2024-06-13 ⋅ 阅读:(73) ⋅ 点赞:(0)

在三维图形中,动画和交互是使场景更具动态性和用户参与度的关键因素。Three.js 提供了丰富的 API 和工具来实现各种动画效果和交互功能。在这一章中,我们将深入学习如何使用 Three.js 实现动画和交互。

7.1 基本动画原理

动画的基本原理是在每一帧中更新物体的属性(如位置、旋转、缩放等),然后重新渲染场景。在 Three.js 中,我们通常使用 requestAnimationFrame 来创建一个循环,不断更新场景并渲染。

示例代码:
// 创建一个场景
const scene = new THREE.Scene();

// 创建一个相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.position.z = 5;

// 创建一个渲染器并添加到HTML文档中
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);

// 动画循环函数
function animate() {
    requestAnimationFrame(animate); // 请求下一帧动画
    cube.rotation.x += 0.01; // 更新立方体的旋转角度
    cube.rotation.y += 0.01;
    renderer.render(scene, camera); // 渲染场景
}
animate();

7.2 使用 requestAnimationFrame 实现动画

requestAnimationFrame 是一个高效的浏览器原生方法,用于告诉浏览器你希望执行一个动画,并在重绘之前调用指定的函数来更新动画。

示例代码:
function animate() {
    requestAnimationFrame(animate); // 请求下一帧动画
    cube.rotation.x += 0.01; // 更新立方体的旋转角度
    cube.rotation.y += 0.01;
    renderer.render(scene, camera); // 渲染场景
}
animate(); // 启动动画循环

7.3 基础交互事件

Three.js 支持多种交互事件,如鼠标点击、移动等。我们可以使用 Raycaster 来检测用户交互并做出响应。

示例代码:
// 创建一个 Raycaster 和一个鼠标向量
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();

// 添加鼠标移动事件监听器
document.addEventListener('mousemove', onMouseMove, false);

function onMouseMove(event) {
    // 将鼠标位置归一化到 -1 到 1 之间
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
}

function animate() {
    requestAnimationFrame(animate);
    raycaster.setFromCamera(mouse, camera); // 使用鼠标位置和相机更新 Raycaster
    const intersects = raycaster.intersectObjects(scene.children); // 计算射线与场景对象的交集

    for (let i = 0; i < intersects.length; i++) {
        intersects[i].object.material.color.set(0xff0000); // 如果相交,改变物体颜色
    }

    renderer.render(scene, camera);
}
animate();

7.4 轨道控制器 (OrbitControls)

轨道控制器允许用户通过拖拽鼠标来旋转、缩放和平移相机视角。Three.js 提供了一个非常方便的轨道控制器 OrbitControls

示例代码:
// 引入 OrbitControls 脚本
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

// 创建 OrbitControls 并绑定到相机和渲染器的 DOM 元素
const controls = new OrbitControls(camera, renderer.domElement);

// 在动画循环中更新控制器
function animate() {
    requestAnimationFrame(animate);
    controls.update(); // 更新控制器状态
    renderer.render(scene, camera);
}
animate();

7.5 使用 GSAP 实现高级动画

GSAP(GreenSock Animation Platform)是一个功能强大的 JavaScript 动画库,可以用于创建复杂的动画效果。我们可以结合 GSAP 和 Three.js 来实现高级动画。

示例代码:
// 引入 GSAP 库
import { gsap } from 'gsap';

// 使用 GSAP 创建一个简单的动画
gsap.to(cube.rotation, { duration: 2, x: Math.PI * 2, repeat: -1, yoyo: true });

function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
}
animate();

7.6 鼠标拖拽交互

通过监听鼠标事件,我们可以实现物体的拖拽功能。下面是一个简单的例子,展示如何通过鼠标拖拽来移动物体。

示例代码:
let isDragging = false;
let previousMousePosition = {
    x: 0,
    y: 0
};

document.addEventListener('mousedown', function(e) {
    isDragging = true;
});

document.addEventListener('mousemove', function(e) {
    if (isDragging) {
        let deltaMove = {
            x: e.offsetX - previousMousePosition.x,
            y: e.offsetY - previousMousePosition.y
        };

        cube.rotation.y += deltaMove.x * 0.01;
        cube.rotation.x += deltaMove.y * 0.01;
    }

    previousMousePosition = {
        x: e.offsetX,
        y: e.offsetY
    };
});

document.addEventListener('mouseup', function(e) {
    isDragging = false;
});

通过这几节的学习,读者应该能够在 Three.js 中实现基本的动画效果,并且能够通过鼠标和轨道控制器进行简单的交互。掌握动画和交互,可以让你的三维场景更加生动和互动。