vue3+three.js的理解与简单使用示例代码
更新时间:2026年02月10日 10:21:01 作者:行咘行啊细狗
Three.js是一个基于WebGL的开源JavaScript 3D引擎,它简化了Web 3D开发流程,让开发者能够轻松创建3D场景、动画和交互体验,这篇文章主要介绍了vue3+three.js理解与简单使用的相关资料,需要的朋友可以参考下
一、tres.js的安装
npm i @tresjs/core @tresjs/cientos three
二、three.js的一些基本概念
1、Scene(场景,可以想象成一个空房间。):(这里介绍的是three.js的手动创建)
2、Camera(相机) - 观众的眼睛
3、 Renderer(渲染器) - 摄影师
4、Object(物体) - 演员
// 手动创建一切 ⚙️ const scene = new THREE.Scene() // 手动造房间 const camera = new THREE.PerspectiveCamera() // 手动买相机 const renderer = new THREE.WebGLRenderer() // 手动雇摄影师 // 手动组合所有东西 scene.add(mesh) // 手动放家具 scene.add(light) // 手动装电灯 renderer.render(scene, camera) // 手动拍照
记住:没有 Scene(房间),你的 3D 东西就飘在空中,看不见也摸不着!
三、tres.js的简单示例(自动化创建thrss.js的关键要素):
<template>
<!-- 主容器,确保3D场景充满整个视口 -->
<div style="width: 100%; height: 100vh">
<!--
TresCanvas 是 3D 场景的根容器,可以理解成一个工地,它自动创建了:
1. Scene(场景/空房间)
2. Renderer(渲染器)
3. Canvas(画布)
4. 自动渲染循环
window-size: 自动填充整个窗口大小
clear-color: 背景颜色,这里设置为青绿色
-->
<TresCanvas window-size clear-color="#82DBC5">
<!--
透视相机,模拟人眼视角
:position="[3, 3, 3]": 相机在3D空间中的位置 [x, y, z]
:look-at="[0, 0, 0]": 相机看向的点 [x, y, z],这里设置为世界原点
-->
<TresPerspectiveCamera :position="[3, 3, 3]" :look-at="[0, 0, 0]" />
<!--
🎮 轨道控制器,提供用户交互功能:
- 左键拖拽:旋转场景
- 右键拖拽:平移场景
- 滚轮缩放:缩放场景
无需额外配置,开箱即用
-->
<OrbitControls />
<!--
📦 立方体网格
TresMesh可以理解成工地的某一栋房子,包含几何体和材质
-->
<TresMesh>
<!--
📐 立方体几何体,定义形状
:args="[1, 1, 1]": 定义立方体的尺寸 [宽度, 高度, 深度]
-->
<TresBoxGeometry :args="[1, 1, 1]" />
<!--
🎨 基础网格材质,为几何体添加外观属性
color="red": 基础颜色设置为红色
:wireframe="true": 启用线框模式,只显示边框
-->
<TresMeshBasicMaterial color="red" :wireframe="true" />
</TresMesh>
<!--
💡 环境光,模拟环境反射光
:intensity="0.8": 光照强度为0.8
环境光无方向性,为整个场景提供均匀的基础照明
-->
<TresAmbientLight :intensity="0.8" />
<!--
🎯 坐标轴辅助工具,帮助理解3D空间方向
:args="[5]": 坐标轴长度为5个单位
红色=X轴,绿色=Y轴,蓝色=Z轴
-->
<TresAxesHelper :args="[5]" />
</TresCanvas>
</div>
</template>
<script setup>
// 导入Tres.js核心组件
import { TresCanvas } from "@tresjs/core";
// 导入轨道控制器组件
import { OrbitControls } from "@tresjs/cientos";
</script>
四、效果图:

五、tres.js实现iphone手机3D模型组件展示:
<template>
<div class="iphone-showcase">
<!--
TresCanvas是Tres.js的根组件,相当于Three.js的WebGL渲染器
window-size: 自动填充整个窗口大小
:clear-color: 绑定背景颜色,使用Vue的响应式数据
-->
<TresCanvas window-size :clear-color="currentColor">
<!--
透视相机组件
:position: 相机在3D空间中的位置 [x, y, z]
:look-at: 相机看向的点 [x, y, z],这里设置为世界原点
:fov: 视野角度,60度是接近人眼的自然视角
-->
<TresPerspectiveCamera
:position="[cameraPosition.x, cameraPosition.y, cameraPosition.z]"
:look-at="[0, 0, 0]"
:fov="60"
/>
<!--
轨道控制器,提供用户交互功能:
- 左键拖拽:旋转场景
- 右键拖拽:平移场景
- 鼠标滚轮:缩放场景
enable-damping: 启用阻尼效果,使移动更平滑
damping-factor: 阻尼系数,值越小移动越平滑
:auto-rotate: 绑定自动旋转状态
auto-rotate-speed: 自动旋转的速度
-->
<OrbitControls
enable-damping
damping-factor="0.05"
:auto-rotate="autoRotate"
auto-rotate-speed="1"
/>
<!-- 光源系统 -->
<!-- 平行光:模拟太阳光,有明确的方向性,产生阴影 -->
<TresDirectionalLight :position="[5, 5, 5]" :intensity="1.5" />
<!-- 环境光:模拟环境反射光,无方向,提供基础照明 -->
<TresAmbientLight :intensity="0.8" />
<!-- 点光源:模拟灯泡,从点向四周发射光线 -->
<TresPointLight :position="[2, 3, -2]" :intensity="0.8" color="#4ecdc4" />
<!-- iPhone模型组件 -->
<IPhoneModel />
<!-- 辅助工具(主要用于调试) -->
<!-- 坐标轴辅助:红色=X轴,绿色=Y轴,蓝色=Z轴,帮助理解3D空间方向 -->
<TresAxesHelper :args="[3]" />
<!-- 网格辅助:10x10的网格,帮助定位和观察场景比例 -->
<TresGridHelper :args="[10, 10]" :position="[0, -1.5, 0]" />
</TresCanvas>
<!-- 控制面板 -->
<div class="controls">
<button @click="toggleAutoRotate">
{{ autoRotate ? "⏸️ 暂停" : "▶️ 旋转" }}
</button>
<button @click="changeColor">🎨 换色</button>
</div>
</div>
</template>
<script setup>
import {
ref,
reactive,
onMounted,
onUnmounted,
watch,
h,
shallowRef,
} from "vue";
import { TresCanvas } from "@tresjs/core";
import { OrbitControls } from "@tresjs/cientos";
import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
//自动旋转控制,初始值为true(启用自动旋转)
const autoRotate = ref(true);
/**
* 相机位置
* reactive用于对象类型数据,初始位置为[0, 0.5, 3]
* - x: 水平位置
* - y: 垂直位置
* - z: 深度位置
*/
const cameraPosition = reactive({ x: 0, y: 0.5, z: 3 });
//背景颜色
const currentColor = ref("#1a1a2e");
/**
* iPhone模型引用
* 使用shallowRef优化性能,只对.value的变化做出响应
*/
const iphoneModel = shallowRef(null);
// ========== 动画循环控制 ==========
// 动画帧ID,用于控制动画循环
let animationId = null;
// ========== 用户交互方法 ==========
//旋转、暂停
const toggleAutoRotate = () => {
autoRotate.value = !autoRotate.value;
};
//换色
const changeColor = () => {
const colors = ["#1a1a2e", "#0f3460", "#533483", "#16213e"];
const currentIndex = colors.indexOf(currentColor.value);
currentColor.value = colors[(currentIndex + 1) % colors.length];
};
// ========== 模型加载逻辑 ==========
//加载iPhone模型
const loadIPhoneModel = () => {
// 创建GLTF加载器实例(GLTFLoader是加载GLTF格式的3D模型文件)
const loader = new GLTFLoader();
// 模型文件路径(需要放在public/models/目录下)
const modelPath = "/models/scene.gltf";
/**
* 加载GLTF模型
* 参数1: 模型文件路径
* 参数2: 加载成功回调函数
* 参数3: 加载进度回调函数
* 参数4: 加载失败回调函数
*/
loader.load(
modelPath,
// 加载成功回调
// const gltf = {
// scene: THREE.Group, // 整个3D场景(最重要的部分)
// scenes: Array, // 场景数组(通常只有一个场景)
// cameras: Array, // 相机数组
// animations: Array, // 动画数据数组
// asset: Object, // 资源信息(作者、版本等)
// userData: Object // 用户自定义数据
// };
(gltf) => {
// 检查场景是否有效
if (gltf.scene) {
// 克隆模型,避免直接修改原始数据
const model = gltf.scene.clone();
//确保模型正确显示。网格(Mesh):3D模型的基本组成单位,包含几何体(形状)和材质(外观)
model.traverse((child) => {
if (child.isMesh) {
child.visible = true;
}
});
//创建一个刚好能完全包围这个3D模型的矩形边界框,用于获取模型的精确尺寸和位置信息,以便进行居中、缩放等标准化处理。
const box = new THREE.Box3().setFromObject(model);
// 获取模型尺寸
const size = box.getSize(new THREE.Vector3());
// 获取模型中心点
const center = box.getCenter(new THREE.Vector3());
// 将模型移动到世界原点(0,0,0)
model.position.x -= center.x;
model.position.y -= center.y;
model.position.z -= center.z;
// 根据最大尺寸缩放模型到合适大小
const maxSize = Math.max(size.x, size.y, size.z);
// 缩放到0.8单位大小,确保模型不会太大或太小
const scale = maxSize > 0 ? 0.8 / maxSize : 1;
model.scale.setScalar(scale);
// 更新模型引用
iphoneModel.value = model;
}
},
// 加载进度回调
// const progress = {
// loaded: 1024000, // 已加载的字节数 (bytes)
// total: 5120000, // 总字节数 (bytes)
// lengthComputable: true // 是否知道总大小
// };
(progress) => {
// 在控制台显示加载进度,便于调试
console.log(
`加载进度: ${((progress.loaded / progress.total) * 100).toFixed(2)}%`
);
},
// 加载失败回调
(error) => {
console.error("模型加载失败:", error);
}
);
};
// ========== iPhone模型组件 ==========
const IPhoneModel = () => {
if (iphoneModel.value) {
// 模型已加载:渲染3D模型
return h("primitive", { object: iphoneModel.value });
}
// 模型未加载:不渲染内容
return null;
};
// ========== 动画系统 ==========
const animate = () => {
// 1. 动画函数定义
if (autoRotate.value) {
// 2. 动画条件控制
const time = Date.now() * 0.001; // 3. 时间变量
cameraPosition.x = Math.sin(time) * 3; // 4. 属性变化(动画核心)
cameraPosition.z = Math.cos(time) * 3;
}
animationId = requestAnimationFrame(animate); // 5. 循环机制
};
//开始动画循环
const startAnimation = () => {
if (!animationId) {
animationId = requestAnimationFrame(animate);
}
};
//停止动画循环
const stopAnimation = () => {
if (animationId) {
cancelAnimationFrame(animationId);
animationId = null; // 重置ID
}
};
// ========== 响应式监听和生命周期 ==========
//监听旋转还是暂停
watch(autoRotate, (newVal) => {
if (newVal) {
startAnimation(); // 开始动画循环
} else {
stopAnimation(); // 停止动画循环
}
});
onMounted(() => {
if (autoRotate.value) {
startAnimation(); // 开始动画循环
}
// 加载iPhone模型
loadIPhoneModel();
});
onUnmounted(() => {
stopAnimation(); // 停止动画循环,避免内存泄漏
});
</script>
<style scoped>
/* 主容器样式 */
.iphone-showcase {
width: 100%;
height: 100vh;
position: relative;
}
/* 控制面板样式 */
.controls {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 10px;
z-index: 100;
}
/* 控制按钮样式 */
.controls button {
padding: 10px 20px;
background: rgba(255, 255, 255, 0.9);
border: none;
border-radius: 25px;
color: #333;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
}
/* 按钮悬停效果 */
.controls button:hover {
background: rgba(255, 255, 255, 1);
transform: translateY(-2px);
}
</style>
六、iphone手机3D模型组件下载:
这里使用的是Sketchfab下载的3D模型文件,这里使用的是gltf文件(下载后需要解压,然后将全部的解压文件放到public/models中即可)

七、效果图:

总结
到此这篇关于vue3+three.js理解与简单使用的文章就介绍到这了,更多相关vue3 three.js简单使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!


最新评论