最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue3+three.js的理解與簡(jiǎn)單使用示例代碼

 更新時(shí)間:2026年02月10日 10:21:01   作者:行咘行啊細(xì)狗  
Three.js是一個(gè)基于WebGL的開(kāi)源JavaScript?3D引擎,它簡(jiǎn)化了Web?3D開(kāi)發(fā)流程,讓開(kāi)發(fā)者能夠輕松創(chuàng)建3D場(chǎng)景、動(dòng)畫和交互體驗(yàn),這篇文章主要介紹了vue3+three.js理解與簡(jiǎn)單使用的相關(guā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)買相機(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(畫布)
      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ì)象類型數(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án)控制 ==========

// 動(dòng)畫幀ID,用于控制動(dòng)畫循環(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)畫數(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)畫系統(tǒng) ==========

const animate = () => {
  // 1. 動(dòng)畫函數(shù)定義
  if (autoRotate.value) {
    // 2. 動(dòng)畫條件控制
    const time = Date.now() * 0.001; // 3. 時(shí)間變量
    cameraPosition.x = Math.sin(time) * 3; // 4. 屬性變化(動(dòng)畫核心)
    cameraPosition.z = Math.cos(time) * 3;
  }
  animationId = requestAnimationFrame(animate); // 5. 循環(huán)機(jī)制
};

//開(kāi)始動(dòng)畫循環(huán)
const startAnimation = () => {
  if (!animationId) {
    animationId = requestAnimationFrame(animate);
  }
};

//停止動(dòng)畫循環(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án)
  } else {
    stopAnimation(); // 停止動(dòng)畫循環(huán)
  }
});

onMounted(() => {
  if (autoRotate.value) {
    startAnimation(); // 開(kāi)始動(dòng)畫循環(huán)
  }
  // 加載iPhone模型
  loadIPhoneModel();
});

onUnmounted(() => {
  stopAnimation(); // 停止動(dòng)畫循環(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)文章

  • 分離vue文件中css、js代碼的簡(jiǎn)單技巧

    分離vue文件中css、js代碼的簡(jiǎn)單技巧

    這篇文章主要給大家介紹了關(guān)于分離vue文件中css、js代碼的簡(jiǎn)單技巧,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-03-03
  • vue3?+?async-validator實(shí)現(xiàn)表單驗(yàn)證的示例代碼

    vue3?+?async-validator實(shí)現(xiàn)表單驗(yàn)證的示例代碼

    表單驗(yàn)證可以有效的過(guò)濾不合格的數(shù)據(jù),減少服務(wù)器的開(kāi)銷,并提升用戶的使用體驗(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ù)的方法

    這篇文章主要介紹了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)的解決方法

    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)

    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)

    本文主要介紹了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組件同樣適用)

    這篇文章主要介紹了vxe-table表格組件,編輯單元格詳解(el-table組件同樣適用),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • vue3繼承并擴(kuò)展三方組件完成二次封裝的示例詳解

    vue3繼承并擴(kuò)展三方組件完成二次封裝的示例詳解

    這篇文章主要介紹了vue3繼承并擴(kuò)展三方組件完成二次封裝,文章使用naiveui的Input組件進(jìn)行舉例,elementPlus或者其他組件庫(kù)同理,并通過(guò)代碼示例講解的非常詳細(xì),需要的朋友可以參考下
    2024-03-03
  • vue組件間的通信,子組件向父組件傳值的方式匯總

    vue組件間的通信,子組件向父組件傳值的方式匯總

    這篇文章主要介紹了vue組件間的通信,子組件向父組件傳值的方式匯總,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Vue v-model實(shí)現(xiàn)案例介紹

    Vue v-model實(shí)現(xiàn)案例介紹

    v-model就是vue的雙向綁定的指令,能將頁(yè)面上控件輸入的值同步更新到相關(guān)綁定的data屬性,也會(huì)在更新data綁定屬性時(shí)候,更新頁(yè)面上輸入控件的值
    2022-09-09

最新評(píng)論

兴业县| 伽师县| 方正县| 漳州市| 保山市| 固镇县| 乐安县| 永宁县| 南华县| 顺平县| 桐柏县| 紫阳县| 内乡县| 雅安市| 合水县| 汉沽区| 林口县| 荆门市| 商都县| 绥棱县| 云霄县| 平阴县| 广饶县| 邓州市| 泰安市| 视频| 东乌珠穆沁旗| 木里| 潜江市| 张家港市| 科尔| 新沂市| 台州市| 建湖县| 林西县| 任丘市| 临清市| 西畴县| 古蔺县| 东平县| 顺平县|