当前位置: 首页 > news >正文

第七章 Three.js 动画与交互

在三维图形中,动画和交互是使场景更具动态性和用户参与度的关键因素。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); // 使用鼠标位置和相机更新 Raycasterconst 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 中实现基本的动画效果,并且能够通过鼠标和轨道控制器进行简单的交互。掌握动画和交互,可以让你的三维场景更加生动和互动。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 热门开源项目推荐:技术与地址概览
  • laravel8使用中间件实现xss处理
  • 简单说一下STL中的map容器的特点、底层实现和应用场景【面试】
  • 【云原生】Kubernetes----Rancher助力Kubernetes监控
  • 开发uniapp 小程序时遇到的问题
  • DeepSORT(目标跟踪算法) 卡尔曼滤波 状态向量是如何映射到观测向量(测量向量)的即观测矩阵的构建方式
  • MySQL怎么为表添加描述
  • PR插件-图层抖动弹跳缩放旋转模糊闪烁缩放抖动动作效果预设
  • spring管理的对象通过@Init注解修饰的方法不会在new对象的时候触发
  • 【面向就业的Linux基础】从入门到熟练,探索Linux的秘密(二)
  • css3新增的伪类有哪些
  • mysql8.0 sql_mode与ONLY_FULL_GROUP_BY报错
  • 《广告数据定量分析》核心内容——搜索广告投放优化方法
  • 湖州等保测评公司有几家?在那里?电话多少?
  • mtk镜像签名
  • (ckeditor+ckfinder用法)Jquery,js获取ckeditor值
  • [case10]使用RSQL实现端到端的动态查询
  • 【162天】黑马程序员27天视频学习笔记【Day02-上】
  • 【React系列】如何构建React应用程序
  • 【翻译】Mashape是如何管理15000个API和微服务的(三)
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • android 一些 utils
  • CSS相对定位
  • exports和module.exports
  • Git的一些常用操作
  • nodejs实现webservice问题总结
  • PAT A1017 优先队列
  • php中curl和soap方式请求服务超时问题
  • Redis 中的布隆过滤器
  • SpiderData 2019年2月25日 DApp数据排行榜
  • 从地狱到天堂,Node 回调向 async/await 转变
  • 开放才能进步!Angular和Wijmo一起走过的日子
  • 聊一聊前端的监控
  • 码农张的Bug人生 - 见面之礼
  • 前嗅ForeSpider中数据浏览界面介绍
  • 适配mpvue平台的的微信小程序日历组件mpvue-calendar
  • 想晋级高级工程师只知道表面是不够的!Git内部原理介绍
  • 再谈express与koa的对比
  • [地铁译]使用SSD缓存应用数据——Moneta项目: 低成本优化的下一代EVCache ...
  • ​必胜客礼品卡回收多少钱,回收平台哪家好
  • #1014 : Trie树
  • (4) openssl rsa/pkey(查看私钥、从私钥中提取公钥、查看公钥)
  • (C++哈希表01)
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (Git) gitignore基础使用
  • (void) (_x == _y)的作用
  • (动手学习深度学习)第13章 计算机视觉---图像增广与微调
  • (仿QQ聊天消息列表加载)wp7 listbox 列表项逐一加载的一种实现方式,以及加入渐显动画...
  • (附源码)ssm智慧社区管理系统 毕业设计 101635
  • (三)Kafka离线安装 - ZooKeeper开机自启
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • (一)UDP基本编程步骤
  • (转) Face-Resources
  • (转)C#调用WebService 基础
  • (转)socket Aio demo