🔥 Three.js 一个项目用到:轨道控制器、动画与GUI交互

Three.js是构建Web3D内容的强大工具库。

我看评论区有小伙伴叫我搞web3,会比web3d有前途,😂,回头我看看web3的相关文档搞搞看,最近公司正好在搞web3d,正好借助掘金这个平台分享一下开发3d的一些踩坑记录。

vitethreejs写的,很简单,一个main.js够用了。先去下vitethreejs。做一个完整的Three.js应用,包含了3D场景的基本元素、交互控制和动画效果。

package.json

main.js 引用如下:

首先看效果

🔥 场景初始化与核心组件

构建Three.js应用首先需要设置三个核心要素:

javascript 复制代码
// 创建三维世界容器
const scene = new THREE.Scene();

// 配置观察视角 - 45度透视相机
const camera = new THREE.PerspectiveCamera(
  45, 
  window.innerWidth/window.innerHeight, 
  0.1, 
  1000
);

// 初始化WebGL渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

🔥 视觉辅助系统

🔥 三维坐标指引器

javascript 复制代码
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);

笛卡尔右手系(右手规则)

标识空间方向:

  • 红色箭头 → X轴(左右)
  • 绿色箭头 → Y轴(上下)
  • 蓝色箭头 → Z轴(前后)

🔥 智能视角控制器

javascript 复制代码
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;  // 启用物理阻尼
controls.dampingFactor = 0.05;  // 设置惯性系数

交互方式:

  • 左键拖动 → 环绕观察
  • 滚轮滑动 → 推拉镜头
  • 右键拖动 → 平移场景

🔥 动态动画引擎

创建弹性球体并设置运动轨迹:

javascript 复制代码
// 绿色球体初始化
const sphere = new THREE.Mesh(
  new THREE.SphereGeometry(1, 32, 32),
  new THREE.MeshBasicMaterial({ color: 0x00ff00 })
);
sphere.position.x = -4;
scene.add(sphere);

// 创建补间动画序列
const moveRight = new TWEEN.Tween(sphere.position)
  .to({ x: 4 }, 1000)
  .easing(TWEEN.Easing.Quadratic.InOut);

const moveLeft = new TWEEN.Tween(sphere.position)
  .to({ x: -4 }, 1000);

// 构建循环动画链
moveRight.chain(moveLeft);
moveLeft.chain(moveRight);
moveRight.start();

动画控制参数:

  • .to() 定义目标状态和持续时间
  • .easing() 设置运动曲线(先加速后减速)
  • .chain() 连接动画片段形成循环

🔥 可视化控制面板

集成lil-gui创建调试界面:

javascript 复制代码
const gui = new GUI();

const controlPanel = {
  暂停动画: () => moveRight.stop(),
  恢复动画: () => moveRight.start(),
  运动速度: 1.0
};

gui.add(controlPanel, '暂停动画');
gui.add(controlPanel, '恢复动画');
gui.add(controlPanel, '运动速度', 0.1, 5.0)
  .onChange(val => {
    moveRight.duration(1000/val);
    moveLeft.duration(1000/val);
  });

🔥 自适应响应机制

确保多设备兼容性:

javascript 复制代码
window.addEventListener("resize", () => {
  renderer.setSize(window.innerWidth, window.innerHeight);
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();  // 重计算透视矩阵
});

🔥 核心渲染循环

驱动整个场景运转的引擎:

javascript 复制代码
function renderScene() {
  controls.update();          // 更新控制器
  TWEEN.update();            // 推进动画
  renderer.render(scene, camera);
  requestAnimationFrame(renderScene);
}
renderScene();

整体代码

main.js

js 复制代码
// 导入threejs
import * as THREE from "three";
// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// 导入lil.gui
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
// 导入hdr加载器
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
// 导入gltf加载器
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
// 导入draco解码器
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";
// 导入tween
import * as TWEEN from "three/examples/jsm/libs/tween.module.js";

// 创建场景
const scene = new THREE.Scene();

// 创建相机
const camera = new THREE.PerspectiveCamera(
  45, // 视角
  window.innerWidth / window.innerHeight, // 宽高比(根据窗口尺寸)
  0.1, // 近平面,近裁剪面(小于此距离的对象不显示)
  1000 // 远平面,远裁剪面(大于此距离的对象不显示)
);

// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// 设置相机位置
camera.position.z = 15;
camera.position.y = 2;
camera.position.x = 2;
camera.lookAt(0, 0, 0);

// 添加世界坐标辅助器
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);

// 添加轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 设置带阻尼的惯性
controls.enableDamping = true;
// 设置阻尼系数
controls.dampingFactor = 0.05;
// 设置旋转速度
// controls.autoRotate = true;

// 渲染函数
function animate() {
  controls.update();
  requestAnimationFrame(animate);
  // 渲染
  renderer.render(scene, camera);
  // 更新tween
  TWEEN.update();
}
animate();

// 监听窗口变化
window.addEventListener("resize", () => {
  // 重置渲染器宽高比
  renderer.setSize(window.innerWidth, window.innerHeight);
  // 重置相机宽高比
  camera.aspect = window.innerWidth / window.innerHeight;
  // 更新相机投影矩阵
  camera.updateProjectionMatrix();
});

// 创建GUI
const gui = new GUI();

// 创建1个球
const sphere1 = new THREE.Mesh(
  new THREE.SphereGeometry(1, 32, 32),
  new THREE.MeshBasicMaterial({
    color: 0x00ff00,
  })
);
sphere1.position.x = -4; // 初始位置:x轴-4处
scene.add(sphere1);

const tween = new TWEEN.Tween(sphere1.position);
tween.to({ x: 4 }, 1000);
tween.onUpdate(() => {
  console.log(sphere1.position.x);
});
// 设置缓动函数
tween.easing(TWEEN.Easing.Quadratic.InOut);

let tween2 = new TWEEN.Tween(sphere1.position);
tween2.to({ x: -4 }, 1000);

tween.chain(tween2);
tween2.chain(tween);
// 启动补间动画
tween.start();
tween.onStart(() => {
  console.log("开始");
});
tween.onComplete(() => {
  console.log("结束");
});
tween.onStop(() => {
  console.log("停止");
});
tween.onUpdate(() => {
  console.log("更新");
});
let params = {
  stop: function () {
    tween.stop();
  },
};

这个小球正在执行一个来回往复的水平移动动画:

起点:X轴坐标-4的位置(屏幕左侧)

向右移动:用1秒时间平滑移动到X轴+4的位置(屏幕右侧)

向左返回:再用1秒时间平滑返回起点X轴-4的位置

循环往复:上述过程会无限循环

分别用了:

Three.js:负责3D渲染和场景管理

Tween.js:处理复杂动画和过渡效果

lil-gui:提供调试和控制界面

相关推荐
xw51 小时前
免费的个人网站托管-Cloudflare
服务器·前端
网安Ruler1 小时前
Web开发-PHP应用&Cookie脆弱&Session固定&Token唯一&身份验证&数据库通讯
前端·数据库·网络安全·php·渗透·红队
!win !1 小时前
免费的个人网站托管-Cloudflare
服务器·前端·开发工具
饺子不放糖1 小时前
基于BroadcastChannel的前端多标签页同步方案:让用户体验更一致
前端
饺子不放糖1 小时前
前端性能优化实战:从页面加载到交互响应的全链路优化
前端
Jackson__1 小时前
使用 ICE PKG 开发并发布支持多场景引用的 NPM 包
前端
饺子不放糖1 小时前
前端错误监控与异常处理:构建健壮的Web应用
前端
cos1 小时前
FE Bits 前端周周谈 Vol.1|Hello World、TanStack DB 首个 Beta 版发布
前端·javascript·css
饺子不放糖1 小时前
CSS的float布局,让我怀疑人生
前端
阳光是sunny1 小时前
走进AI(1):细说RAG、MCP、Agent、Function Call
前端·ai编程