Three.js
是构建Web3D
内容的强大工具库。
我看评论区有小伙伴叫我搞
web3
,会比web3d
有前途,😂,回头我看看web3的相关文档搞搞看,最近公司正好在搞web3d
,正好借助掘金这个平台分享一下开发3d
的一些踩坑记录。
用vite
和threejs
写的,很简单,一个main.js
够用了。先去下vite
和threejs
。做一个完整的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:提供调试和控制界面