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

ThreeJS曲线动画:打造炫酷3D路径运动

(一) 效果呈现:

自定义路径运动

在这里插入图片描述

ThreeJS路径与动画部分技术点详细解析

以下是pathway.vue案例中路径创建与动画实现的核心技术点及具体属性:

一、路径创建与可视化

1. CatmullRom曲线定义
const path = new THREE.CatmullRomCurve3([new THREE.Vector3(0, -4, 0),new THREE.Vector3(2, -2, 0),new THREE.Vector3(0, 0, 2),// ...更多点坐标...new THREE.Vector3(0,-4, 0),
]);
  • CatmullRomCurve3:创建平滑的三次样条曲线,通过一系列控制点生成连续的平滑路径
  • Vector3点数组:定义曲线路径的关键点,曲线会通过这些点并在点之间平滑过渡
  • 闭合路径:首尾点坐标相同(均为(0,-4,0)),确保路径形成一个闭合循环
2. 路径点标记
const pointMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const pointGeometry = new THREE.SphereGeometry(0.1, 6, 6);
const points = path.getPoints(path.points.length - 1);
points.forEach(point => {const pointMesh = new THREE.Mesh(pointGeometry, pointMaterial);pointMesh.position.copy(point);scene.add(pointMesh);
});
  • getPoints():获取曲线上的点,此处获取原始控制点
  • SphereGeometry:用于创建标记点的小球几何体,参数含义:
    • radius: 0.1 - 小球半径
    • widthSegments: 6 - 水平分段数
    • heightSegments: 6 - 垂直分段数
  • position.copy():将路径点坐标复制到标记点的位置
3. 路径线条可视化
const points1 = path.getPoints(50);
const geometryLine = new THREE.BufferGeometry().setFromPoints(points1);
const materialLine = new THREE.LineBasicMaterial({ color: 0x000fff });
const line = new THREE.Line(geometryLine, materialLine);
line.computeLineDistances();
scene.add(line);
  • getPoints(50):获取曲线上均匀分布的50个点,点数越多线条越平滑
  • BufferGeometry.setFromPoints():根据点数组创建线条几何体
  • LineBasicMaterial:基础线条材质,设置为蓝色(0x000fff)
  • computeLineDistances():计算线条中各点之间的距离,优化线条渲染效果

二、动画实现

1. 时间控制机制
let time = 0;
function render() {const looptime = 20; // 完整循环所需时间,单位秒const t = (time % looptime) / looptime; // 归一化时间参数t,范围0到1// ...time += 0.01; // 增加时间参数
}
  • looptime:定义动画完整循环的时间(20秒)
  • 归一化时间t:通过(time % looptime) / looptime计算,确保t始终在[0,1]范围内
  • time增量:每次渲染增加0.01,控制动画速度
2. 沿路径移动
const point = path.getPointAt(t); // 获取路径上对应t位置的点
sphere.position.copy(point); // 更新球体位置
  • getPointAt(t):根据归一化时间t获取曲线上的精确位置点
  • position.copy():将获取的点位置应用到球体上,实现沿路径移动
3. 朝向调整
const tangent = path.getTangentAt(t).normalize();
const axis = new THREE.Vector3(0, 1, 0); // 假设Y轴为上方向
const radians = Math.acos(axis.dot(tangent)); // 计算旋转角度
const cross = new THREE.Vector3().crossVectors(axis, tangent).normalize(); // 计算旋转轴
sphere.quaternion.setFromAxisAngle(cross, radians); // 设置球体旋转
  • getTangentAt(t):获取路径上特定位置的切线方向
  • normalize():将向量归一化为单位向量
  • dot():计算两个向量的点积,用于确定夹角
  • acos():计算反余弦值,得到旋转角度(弧度)
  • crossVectors():计算两个向量的叉积,确定旋转轴
  • quaternion.setFromAxisAngle():通过轴角方式设置物体的四元数旋转
4. 场景整体旋转
function animate() {requestAnimationFrame(animate);// 旋转整个场景scene.rotation.y -= 0.001;// 更新轨道控制器controls.update();// 调用渲染函数render()// 渲染场景renderer.render(scene, camera);
}
animate();
  • requestAnimationFrame():创建浏览器优化的动画循环
  • scene.rotation.y:使整个场景绕Y轴缓慢旋转,增强视觉效果
  • controls.update():更新轨道控制器状态,确保交互正常
  • renderer.render():执行场景渲染

这些技术点共同实现了平滑的路径定义、可视化和沿路径的动画效果,包括精确的位置控制和朝向调整,使球体能够自然地沿着预设路径运动。

(二)除了CatmullRomCurve3绘制曲线以外,还有以下几个属性可以绘制曲线:

ThreeJS中常用的曲线类型及属性

除了CatmullRomCurve3外,ThreeJS还提供了多种曲线类型用于不同场景的曲线创建。以下是常用的曲线类型及其主要属性:

1. LineCurve / LineCurve3 - 直线

// 二维直线
const line2d = new THREE.LineCurve(new THREE.Vector2(0, 0), new THREE.Vector2(10, 10));// 三维直线
const line3d = new THREE.LineCurve3(new THREE.Vector3(0, 0, 0), new THREE.Vector3(10, 10, 10));
  • 主要参数:起点和终点的Vector2/Vector3对象
  • 适用场景:创建简单的直线段、坐标轴等

2. QuadraticBezierCurve / QuadraticBezierCurve3 - 二次贝塞尔曲线

// 二维二次贝塞尔曲线
const bezier2d = new THREE.QuadraticBezierCurve(new THREE.Vector2(0, 0),     // 起点new THREE.Vector2(5, 10),    // 控制点new THREE.Vector2(10, 0)     // 终点
);// 三维二次贝塞尔曲线
const bezier3d = new THREE.QuadraticBezierCurve3(new THREE.Vector3(0, 0, 0),  // 起点new THREE.Vector3(5, 10, 5), // 控制点new THREE.Vector3(10, 0, 0)  // 终点
);
  • 主要参数:起点、单个控制点、终点
  • 适用场景:创建平滑的曲线过渡,如路径规划、动画曲线

3. CubicBezierCurve / CubicBezierCurve3 - 三次贝塞尔曲线

// 二维三次贝塞尔曲线
const cubic2d = new THREE.CubicBezierCurve(new THREE.Vector2(0, 0),     // 起点new THREE.Vector2(2.5, 10),  // 控制点1new THREE.Vector2(7.5, -10), // 控制点2new THREE.Vector2(10, 0)     // 终点
);// 三维三次贝塞尔曲线
const cubic3d = new THREE.CubicBezierCurve3(new THREE.Vector3(0, 0, 0),  // 起点new THREE.Vector3(2.5, 10, 5), // 控制点1new THREE.Vector3(7.5, -10, -5), // 控制点2new THREE.Vector3(10, 0, 0)  // 终点
);
  • 主要参数:起点、两个控制点、终点
  • 适用场景:需要更复杂曲率控制的曲线,如字体轮廓、复杂路径

4. EllipseCurve - 椭圆曲线

const ellipse = new THREE.EllipseCurve(0, 0,          // 中心坐标 (x, y)10, 5,         // 半径 (xRadius, yRadius)0, Math.PI * 2, // 起始角度和结束角度false,         // 是否顺时针0              // 旋转角度
);
  • 主要参数:中心点坐标、x/y半径、起始/结束角度、方向、旋转角度
  • 适用场景:创建椭圆、圆形、圆弧等
  • 特别说明:当xRadius和yRadius相等时,就是正圆

5. CircleCurve - 圆弧曲线

const circle = new THREE.CircleCurve(0, 0,      // 中心坐标 (x, y)10,        // 半径0, Math.PI // 起始角度和结束角度
);
  • 主要参数:中心点坐标、半径、起始/结束角度
  • 适用场景:创建圆弧段
  • 注意:这是EllipseCurve的特例,专门用于圆弧

6. ArcCurve - 圆弧曲线(更灵活的版本)

const arc = new THREE.ArcCurve(0, 0,    // 中心坐标 (x, y)10,      // 半径0, Math.PI // 起始角度和结束角度
);
  • 主要参数:中心点坐标、半径、起始/结束角度
  • 适用场景:与CircleCurve类似,但实现方式略有不同

7. SplineCurve / SplineCurve3 - 样条曲线

// 二维样条曲线
const spline2d = new THREE.SplineCurve([new THREE.Vector2(0, 0),new THREE.Vector2(2, 3),new THREE.Vector2(4, 0),new THREE.Vector2(6, 3),new THREE.Vector2(8, 0)
]);// 三维样条曲线
const spline3d = new THREE.SplineCurve3([new THREE.Vector3(0, 0, 0),new THREE.Vector3(2, 3, 1),new THREE.Vector3(4, 0, 2),new THREE.Vector3(6, 3, 1),new THREE.Vector3(8, 0, 0)
]);
  • 主要参数:Vector2/Vector3点数组
  • 适用场景:通过多个点创建平滑曲线
  • 注意:这是CatmullRomCurve的早期版本,功能类似

8. CatmullRomCurve3 - 三次样条曲线(案例中使用的类型)

const curve = new THREE.CatmullRomCurve3([new THREE.Vector3(0, 0, 0),new THREE.Vector3(1, 1, 1),new THREE.Vector3(2, 0, 2),new THREE.Vector3(3, 1, 3)
], false, 'catmullrom', 0.5);
  • 主要参数
    • 点数组:定义曲线形状的控制点
    • closed:是否闭合
    • type:插值类型(‘centripetal’, ‘chordal’, ‘catmullrom’)
    • tension:张力参数,控制曲线的曲率(0-1)
  • 适用场景:需要通过多个点创建平滑、可控的3D路径

9. TubeGeometry - 管状几何体

const path = new THREE.CatmullRomCurve3([...点数组...]);
const tube = new THREE.TubeGeometry(path,  // 路径对象100,   // 分段数0.5,   // 半径12,    // 半径分段数false  // 是否闭合
);
  • 主要参数:路径对象、长度分段数、半径、半径分段数、是否闭合
  • 适用场景:创建沿曲线延伸的管状结构,如管道、隧道等

10. ParametricCurve - 参数化曲线基类

// 自定义参数曲线
class CustomCurve extends THREE.ParametricCurve {constructor() {super();}getPoint(t, optionalTarget = new THREE.Vector3()) {// t从0到1const x = t * 10;const y = Math.sin(t * Math.PI * 2) * 5;const z = Math.cos(t * Math.PI * 2) * 5;return optionalTarget.set(x, y, z);}
}
const customCurve = new CustomCurve();
  • 主要方法:需要重写getPoint(t)方法来定义曲线形状
  • 适用场景:创建自定义数学函数定义的曲线

这些曲线类型可以根据具体需求选择使用,它们都提供了getPoints()、getPointAt()、getTangentAt()等方法来获取曲线上的点和切线,便于创建路径动画和几何形状。

(三)案例源码 vite + threeJs

<!-- 曲线轨道 -->
<template><div id="pathway_container"></div>
</template><script setup>
import { reactive, toRefs, ref, onMounted, nextTick } from 'vue'
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
let scene, camera, renderer, controls, domWidth, domHeight;
function initScene() {// 场景scene = new THREE.Scene();// 相机camera = new THREE.PerspectiveCamera(75, domWidth / domHeight, 0.1, 1000);// 绘制一个圆球const geometry = new THREE.SphereGeometry(0.5, 28, 28);// 半径,宽度分段,高度分段// const material = new THREE.MeshBasicMaterial({ color: 0xf1a000 });// 设置球体为线框模式const material = new THREE.MeshBasicMaterial({ color: 0xf1a000, wireframe: true });const sphere = new THREE.Mesh(geometry, material);scene.add(sphere);// 定义路径 - CatmullRomCurve3 曲线--绘制一个围绕着Y轴螺旋向上的路径const path = new THREE.CatmullRomCurve3([new THREE.Vector3(0, -4, 0),new THREE.Vector3(2, -2, 0),new THREE.Vector3(0, 0, 2),new THREE.Vector3(-2, 2, 0),new THREE.Vector3(0, 4, -2),new THREE.Vector3(2, 6, 0),new THREE.Vector3(0, 8, 2),new THREE.Vector3(-2, 10, 0),new THREE.Vector3(0, 12, -2),new THREE.Vector3(0, 11, -2),new THREE.Vector3(-2, 8, 0),new THREE.Vector3(0, 6, 2),new THREE.Vector3(2, 4, 0),new THREE.Vector3(0,2, -2),new THREE.Vector3(-2, 0, 0),new THREE.Vector3(0, -2, 2),new THREE.Vector3(1, -4, 0),new THREE.Vector3(0,-4, 0),]);// 给path的这几个点添加小球进行标记const pointMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });const pointGeometry = new THREE.SphereGeometry(0.1, 6, 6);const points = path.getPoints(path.points.length - 1);// 给每个点添加一个小球points.forEach(point => {const pointMesh = new THREE.Mesh(pointGeometry, pointMaterial);pointMesh.position.copy(point);scene.add(pointMesh);});// 创建路径的几何体用于显示const points1 = path.getPoints(50);// 创建线条几何体和材质const geometryLine = new THREE.BufferGeometry().setFromPoints(points1);// 创建线条材质 const materialLine = new THREE.LineBasicMaterial({ color: 0x000fff });// 创建线条对象const line = new THREE.Line(geometryLine, materialLine);// 线条更平滑line.computeLineDistances();// 将线条添加到场景中scene.add(line);// 坐标轴辅助线const axesHelper = new THREE.AxesHelper(8);scene.add(axesHelper);// 相机位置调整:向右、向上、向后移动camera.position.set(5, 25, 25);// 设置相机看向原点上方一点,这样原点就会在视图下方camera.lookAt(0, 5, 0);renderer = new THREE.WebGLRenderer();// 设置渲染器大小renderer.setSize(domWidth, domHeight);document.getElementById('pathway_container').appendChild(renderer.domElement);// 轨道控制器controls = new OrbitControls(camera, renderer.domElement);// 启用阻尼效果controls.enableDamping = true;// 轨道控制器阻尼系数// 轨道控制器阻尼系数是一个0到1之间的小数,用于控制轨道控制器的惯性效果。// 当值为0时,轨道控制器没有惯性效果,当值为1时,轨道控制器有最大的惯性效果。controls.dampingFactor = 0.05;// 让geometry沿着路径移动let time = 0;function render() {// 计算沿路径的位置const looptime = 20; // 完整循环所需时间,单位秒const t = (time % looptime) / looptime; // 归一化时间参数t,范围0到1const point = path.getPointAt(t); // 获取路径上对应t位置的点sphere.position.copy(point); // 更新球体位置// 计算切线方向以调整球体朝向const tangent = path.getTangentAt(t).normalize();const axis = new THREE.Vector3(0, 1, 0); // 假设Y轴为上方向const radians = Math.acos(axis.dot(tangent)); // 计算旋转角度const cross = new THREE.Vector3().crossVectors(axis, tangent).normalize(); // 计算旋转轴sphere.quaternion.setFromAxisAngle(cross, radians); // 设置球体旋转time += 0.01; // 增加时间参数   }// 渲染循环function animate() {requestAnimationFrame(animate);// 旋转整个场景scene.rotation.y -= 0.001;// 更新轨道控制器controls.update();// 调用渲染函数render()// 渲染场景renderer.render(scene, camera);}animate();
}
onMounted(() => {nextTick(() => {domWidth = document.getElementById('pathway_container').clientWidth;domHeight = document.getElementById('pathway_container').clientHeight;initScene();})})
</script>
<style scoped>
#pathway_container {width: 100%;height: 100vh;background-color: #f0f0f0;
}
</style>
http://www.dtcms.com/a/515420.html

相关文章:

  • 国产三维CAD工程图特征、公母唇缘有何提升?| 中望3D 2026亮点速递(8)
  • MEMS与CMOS的3D集成技术研究进展
  • 打造高清3D虚拟世界|零基础学习Unity HDRP高清渲染管线(第四天)
  • 做的最好的网站怎样如何做网站赚钱
  • GitHub 热榜项目 - 日榜(2025-10-22)
  • 论文阅读笔记excel的美化
  • Llama-2-7b在昇腾NPU上的六大核心场景性能基准报告
  • Katalon AI 之StudioAssist 偏好设置
  • Android虚拟机配置完整指南:从零开始解决常见问题
  • 本地网站搭建软件丰台石家庄网站建设
  • 智能密码钥匙检测操作与检测条件对应表
  • Bazel下载和安装教程(附安装包)
  • [Java数据结构和算法] 详解 TreeMap 和 TreeSet
  • 光影筑梦 温暖同行 第三届粤港澳大湾区公益网络微电影大赛展映及颁奖礼圆满落幕
  • 直流滤波器 保障直流系统稳定运行的关键
  • 怎么把自己做的网站发布怎么查看什么公司做的网站
  • 数学建模竞赛模板合集(含latex与word模板):国赛、美赛、研赛、其他
  • 本科/硕士毕业论文格式修改大全|word格式修改
  • MySQL5.7一键升级到MySQL8.0
  • 广州网站建设天维知名外贸网站建设公司
  • 论文阅读:ICML 2025 Adversarial Reasoning at Jailbreaking Time
  • STM32USB学习
  • coze使用记录
  • java面试-0220-HashSet、LinkedHashSet、TreeSet实现?和ArrayList区别?
  • 2、WordPress使用--安装gutenverse插件
  • 南和县建设局黄页网站设计之窗
  • NetworkX 最短路径算法选型图
  • 互联网公司软件开发全流程规范文档
  • springboot基于JAVA的二手书籍交易系统的设计与实现(代码+数据库+LW)
  • STM32产品程序测试完整指南