vue3+three.js的理解與簡(jiǎn)單使用示例代碼
一、tres.js的安裝
npm i @tresjs/core @tresjs/cientos three
二、three.js的一些基本概念
1、Scene(場(chǎng)景,可以想象成一個(gè)空房間。):(這里介紹的是three.js的手動(dòng)創(chuàng)建)
2、Camera(相機(jī))? - 觀眾的眼睛
3、 Renderer(渲染器)? - 攝影師
4、Object(物體)? - 演員
// 手動(dòng)創(chuàng)建一切 ?? const scene = new THREE.Scene() // 手動(dòng)造房間 const camera = new THREE.PerspectiveCamera() // 手動(dòng)買(mǎi)相機(jī) const renderer = new THREE.WebGLRenderer() // 手動(dòng)雇攝影師 // 手動(dòng)組合所有東西 scene.add(mesh) // 手動(dòng)放家具 scene.add(light) // 手動(dòng)裝電燈 renderer.render(scene, camera) // 手動(dòng)拍照
記住:沒(méi)有 Scene(房間),你的 3D 東西就飄在空中,看不見(jiàn)也摸不著!
三、tres.js的簡(jiǎn)單示例(自動(dòng)化創(chuàng)建thrss.js的關(guān)鍵要素):
<template>
<!-- 主容器,確保3D場(chǎng)景充滿整個(gè)視口 -->
<div style="width: 100%; height: 100vh">
<!--
TresCanvas 是 3D 場(chǎng)景的根容器,可以理解成一個(gè)工地,它自動(dòng)創(chuàng)建了:
1. Scene(場(chǎng)景/空房間)
2. Renderer(渲染器)
3. Canvas(畫(huà)布)
4. 自動(dòng)渲染循環(huán)
window-size: 自動(dòng)填充整個(gè)窗口大小
clear-color: 背景顏色,這里設(shè)置為青綠色
-->
<TresCanvas window-size clear-color="#82DBC5">
<!--
透視相機(jī),模擬人眼視角
:position="[3, 3, 3]": 相機(jī)在3D空間中的位置 [x, y, z]
:look-at="[0, 0, 0]": 相機(jī)看向的點(diǎn) [x, y, z],這里設(shè)置為世界原點(diǎn)
-->
<TresPerspectiveCamera :position="[3, 3, 3]" :look-at="[0, 0, 0]" />
<!--
?? 軌道控制器,提供用戶交互功能:
- 左鍵拖拽:旋轉(zhuǎn)場(chǎng)景
- 右鍵拖拽:平移場(chǎng)景
- 滾輪縮放:縮放場(chǎng)景
無(wú)需額外配置,開(kāi)箱即用
-->
<OrbitControls />
<!--
?? 立方體網(wǎng)格
TresMesh可以理解成工地的某一棟房子,包含幾何體和材質(zhì)
-->
<TresMesh>
<!--
?? 立方體幾何體,定義形狀
:args="[1, 1, 1]": 定義立方體的尺寸 [寬度, 高度, 深度]
-->
<TresBoxGeometry :args="[1, 1, 1]" />
<!--
?? 基礎(chǔ)網(wǎng)格材質(zhì),為幾何體添加外觀屬性
color="red": 基礎(chǔ)顏色設(shè)置為紅色
:wireframe="true": 啟用線框模式,只顯示邊框
-->
<TresMeshBasicMaterial color="red" :wireframe="true" />
</TresMesh>
<!--
?? 環(huán)境光,模擬環(huán)境反射光
:intensity="0.8": 光照強(qiáng)度為0.8
環(huán)境光無(wú)方向性,為整個(gè)場(chǎng)景提供均勻的基礎(chǔ)照明
-->
<TresAmbientLight :intensity="0.8" />
<!--
?? 坐標(biāo)軸輔助工具,幫助理解3D空間方向
:args="[5]": 坐標(biāo)軸長(zhǎng)度為5個(gè)單位
紅色=X軸,綠色=Y軸,藍(lán)色=Z軸
-->
<TresAxesHelper :args="[5]" />
</TresCanvas>
</div>
</template>
<script setup>
// 導(dǎo)入Tres.js核心組件
import { TresCanvas } from "@tresjs/core";
// 導(dǎo)入軌道控制器組件
import { OrbitControls } from "@tresjs/cientos";
</script>
四、效果圖:

五、tres.js實(shí)現(xiàn)iphone手機(jī)3D模型組件展示:
<template>
<div class="iphone-showcase">
<!--
TresCanvas是Tres.js的根組件,相當(dāng)于Three.js的WebGL渲染器
window-size: 自動(dòng)填充整個(gè)窗口大小
:clear-color: 綁定背景顏色,使用Vue的響應(yīng)式數(shù)據(jù)
-->
<TresCanvas window-size :clear-color="currentColor">
<!--
透視相機(jī)組件
:position: 相機(jī)在3D空間中的位置 [x, y, z]
:look-at: 相機(jī)看向的點(diǎn) [x, y, z],這里設(shè)置為世界原點(diǎn)
:fov: 視野角度,60度是接近人眼的自然視角
-->
<TresPerspectiveCamera
:position="[cameraPosition.x, cameraPosition.y, cameraPosition.z]"
:look-at="[0, 0, 0]"
:fov="60"
/>
<!--
軌道控制器,提供用戶交互功能:
- 左鍵拖拽:旋轉(zhuǎn)場(chǎng)景
- 右鍵拖拽:平移場(chǎng)景
- 鼠標(biāo)滾輪:縮放場(chǎng)景
enable-damping: 啟用阻尼效果,使移動(dòng)更平滑
damping-factor: 阻尼系數(shù),值越小移動(dòng)越平滑
:auto-rotate: 綁定自動(dòng)旋轉(zhuǎn)狀態(tài)
auto-rotate-speed: 自動(dòng)旋轉(zhuǎn)的速度
-->
<OrbitControls
enable-damping
damping-factor="0.05"
:auto-rotate="autoRotate"
auto-rotate-speed="1"
/>
<!-- 光源系統(tǒng) -->
<!-- 平行光:模擬太陽(yáng)光,有明確的方向性,產(chǎn)生陰影 -->
<TresDirectionalLight :position="[5, 5, 5]" :intensity="1.5" />
<!-- 環(huán)境光:模擬環(huán)境反射光,無(wú)方向,提供基礎(chǔ)照明 -->
<TresAmbientLight :intensity="0.8" />
<!-- 點(diǎn)光源:模擬燈泡,從點(diǎn)向四周發(fā)射光線 -->
<TresPointLight :position="[2, 3, -2]" :intensity="0.8" color="#4ecdc4" />
<!-- iPhone模型組件 -->
<IPhoneModel />
<!-- 輔助工具(主要用于調(diào)試) -->
<!-- 坐標(biāo)軸輔助:紅色=X軸,綠色=Y軸,藍(lán)色=Z軸,幫助理解3D空間方向 -->
<TresAxesHelper :args="[3]" />
<!-- 網(wǎng)格輔助:10x10的網(wǎng)格,幫助定位和觀察場(chǎng)景比例 -->
<TresGridHelper :args="[10, 10]" :position="[0, -1.5, 0]" />
</TresCanvas>
<!-- 控制面板 -->
<div class="controls">
<button @click="toggleAutoRotate">
{{ autoRotate ? "?? 暫停" : "?? 旋轉(zhuǎn)" }}
</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";
//自動(dòng)旋轉(zhuǎn)控制,初始值為true(啟用自動(dòng)旋轉(zhuǎn))
const autoRotate = ref(true);
/**
* 相機(jī)位置
* reactive用于對(duì)象類(lèi)型數(shù)據(jù),初始位置為[0, 0.5, 3]
* - x: 水平位置
* - y: 垂直位置
* - z: 深度位置
*/
const cameraPosition = reactive({ x: 0, y: 0.5, z: 3 });
//背景顏色
const currentColor = ref("#1a1a2e");
/**
* iPhone模型引用
* 使用shallowRef優(yōu)化性能,只對(duì).value的變化做出響應(yīng)
*/
const iphoneModel = shallowRef(null);
// ========== 動(dòng)畫(huà)循環(huán)控制 ==========
// 動(dòng)畫(huà)幀ID,用于控制動(dòng)畫(huà)循環(huán)
let animationId = null;
// ========== 用戶交互方法 ==========
//旋轉(zhuǎn)、暫停
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 = () => {
// 創(chuàng)建GLTF加載器實(shí)例(GLTFLoader是加載GLTF格式的3D模型文件)
const loader = new GLTFLoader();
// 模型文件路徑(需要放在public/models/目錄下)
const modelPath = "/models/scene.gltf";
/**
* 加載GLTF模型
* 參數(shù)1: 模型文件路徑
* 參數(shù)2: 加載成功回調(diào)函數(shù)
* 參數(shù)3: 加載進(jìn)度回調(diào)函數(shù)
* 參數(shù)4: 加載失敗回調(diào)函數(shù)
*/
loader.load(
modelPath,
// 加載成功回調(diào)
// const gltf = {
// scene: THREE.Group, // 整個(gè)3D場(chǎng)景(最重要的部分)
// scenes: Array, // 場(chǎng)景數(shù)組(通常只有一個(gè)場(chǎng)景)
// cameras: Array, // 相機(jī)數(shù)組
// animations: Array, // 動(dòng)畫(huà)數(shù)據(jù)數(shù)組
// asset: Object, // 資源信息(作者、版本等)
// userData: Object // 用戶自定義數(shù)據(jù)
// };
(gltf) => {
// 檢查場(chǎng)景是否有效
if (gltf.scene) {
// 克隆模型,避免直接修改原始數(shù)據(jù)
const model = gltf.scene.clone();
//確保模型正確顯示。網(wǎng)格(Mesh):3D模型的基本組成單位,包含幾何體(形狀)和材質(zhì)(外觀)
model.traverse((child) => {
if (child.isMesh) {
child.visible = true;
}
});
//創(chuàng)建一個(gè)剛好能完全包圍這個(gè)3D模型的矩形邊界框,用于獲取模型的精確尺寸和位置信息,以便進(jìn)行居中、縮放等標(biāo)準(zhǔn)化處理。
const box = new THREE.Box3().setFromObject(model);
// 獲取模型尺寸
const size = box.getSize(new THREE.Vector3());
// 獲取模型中心點(diǎn)
const center = box.getCenter(new THREE.Vector3());
// 將模型移動(dòng)到世界原點(diǎn)(0,0,0)
model.position.x -= center.x;
model.position.y -= center.y;
model.position.z -= center.z;
// 根據(jù)最大尺寸縮放模型到合適大小
const maxSize = Math.max(size.x, size.y, size.z);
// 縮放到0.8單位大小,確保模型不會(huì)太大或太小
const scale = maxSize > 0 ? 0.8 / maxSize : 1;
model.scale.setScalar(scale);
// 更新模型引用
iphoneModel.value = model;
}
},
// 加載進(jìn)度回調(diào)
// const progress = {
// loaded: 1024000, // 已加載的字節(jié)數(shù) (bytes)
// total: 5120000, // 總字節(jié)數(shù) (bytes)
// lengthComputable: true // 是否知道總大小
// };
(progress) => {
// 在控制臺(tái)顯示加載進(jìn)度,便于調(diào)試
console.log(
`加載進(jìn)度: ${((progress.loaded / progress.total) * 100).toFixed(2)}%`
);
},
// 加載失敗回調(diào)
(error) => {
console.error("模型加載失敗:", error);
}
);
};
// ========== iPhone模型組件 ==========
const IPhoneModel = () => {
if (iphoneModel.value) {
// 模型已加載:渲染3D模型
return h("primitive", { object: iphoneModel.value });
}
// 模型未加載:不渲染內(nèi)容
return null;
};
// ========== 動(dòng)畫(huà)系統(tǒng) ==========
const animate = () => {
// 1. 動(dòng)畫(huà)函數(shù)定義
if (autoRotate.value) {
// 2. 動(dòng)畫(huà)條件控制
const time = Date.now() * 0.001; // 3. 時(shí)間變量
cameraPosition.x = Math.sin(time) * 3; // 4. 屬性變化(動(dòng)畫(huà)核心)
cameraPosition.z = Math.cos(time) * 3;
}
animationId = requestAnimationFrame(animate); // 5. 循環(huán)機(jī)制
};
//開(kāi)始動(dòng)畫(huà)循環(huán)
const startAnimation = () => {
if (!animationId) {
animationId = requestAnimationFrame(animate);
}
};
//停止動(dòng)畫(huà)循環(huán)
const stopAnimation = () => {
if (animationId) {
cancelAnimationFrame(animationId);
animationId = null; // 重置ID
}
};
// ========== 響應(yīng)式監(jiān)聽(tīng)和生命周期 ==========
//監(jiān)聽(tīng)旋轉(zhuǎn)還是暫停
watch(autoRotate, (newVal) => {
if (newVal) {
startAnimation(); // 開(kāi)始動(dòng)畫(huà)循環(huán)
} else {
stopAnimation(); // 停止動(dòng)畫(huà)循環(huán)
}
});
onMounted(() => {
if (autoRotate.value) {
startAnimation(); // 開(kāi)始動(dòng)畫(huà)循環(huán)
}
// 加載iPhone模型
loadIPhoneModel();
});
onUnmounted(() => {
stopAnimation(); // 停止動(dòng)畫(huà)循環(huán),避免內(nèi)存泄漏
});
</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手機(jī)3D模型組件下載:
這里使用的是Sketchfab下載的3D模型文件,這里使用的是gltf文件(下載后需要解壓,然后將全部的解壓文件放到public/models中即可)

七、效果圖:

總結(jié)
到此這篇關(guān)于vue3+three.js理解與簡(jiǎn)單使用的文章就介紹到這了,更多相關(guān)vue3 three.js簡(jiǎn)單使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue3?+?async-validator實(shí)現(xiàn)表單驗(yàn)證的示例代碼
表單驗(yàn)證可以有效的過(guò)濾不合格的數(shù)據(jù),減少服務(wù)器的開(kāi)銷(xiāo),并提升用戶的使用體驗(yàn),今天我們使用?vue3?來(lái)做一個(gè)表單驗(yàn)證的例子,需要的朋友跟隨小編一起學(xué)習(xí)下吧2022-06-06
VUE在線調(diào)用阿里Iconfont圖標(biāo)庫(kù)的方法
這篇文章主要介紹了VUE在線調(diào)用阿里Iconfont圖標(biāo)庫(kù)的方法,內(nèi)容是圍繞VUE前端和阿里Iconfont圖標(biāo)庫(kù)展開(kāi)的,經(jīng)歷了從網(wǎng)站上東拼西湊圖標(biāo)的時(shí)代,大概是15~16年左右我開(kāi)始解除阿里Iconfont圖標(biāo)庫(kù),剛開(kāi)始就只會(huì)下載圖標(biāo)使用,需要的朋友可以參考下2021-10-10
vue.js與element-ui實(shí)現(xiàn)菜單樹(shù)形結(jié)構(gòu)的解決方法
本文通過(guò)實(shí)例給大家介紹了vue.js與element-ui實(shí)現(xiàn)菜單樹(shù)形結(jié)構(gòu),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2018-04-04
Element通過(guò)v-for循環(huán)渲染的form表單校驗(yàn)的實(shí)現(xiàn)
日常業(yè)務(wù)開(kāi)發(fā)中,form表單校驗(yàn)是一個(gè)很常見(jiàn)的問(wèn)題,本文主要介紹了Element通過(guò)v-for循環(huán)渲染的form表單校驗(yàn)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04
element中el-table中的el-input校驗(yàn)的實(shí)現(xiàn)
本文主要介紹了element中el-table中的el-input校驗(yàn)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
vxe-table表格組件,編輯單元格詳解(el-table組件同樣適用)
這篇文章主要介紹了vxe-table表格組件,編輯單元格詳解(el-table組件同樣適用),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-04-04

