vue3 中 練習 3d-force-graph 中 img-nodes項目
- 首先要搞清楚需要的那些功能的插件是哪些
- 引入插件 three.js 和 3d-force-graph
1 import * as THREE from "three"; 2 import ForceGraph3D from "3d-force-graph";
- 最基礎的:聲明一個div容器渲染頁面使用
1 <template> 2 <div ref="container"></div> 3 </template>
注:在vue3中的setup語法糖推薦使用ref在組建中創建一個可響應式的引用,通過ref可以輕松訪問要操作的DOM,同時在script中創建一個container的引用,并將ref函數初始化為null,代碼如下:
1 const container = ref(null)
- 先上代碼
1 <template> 2 <div ref="container"></div> 3 </template> 4 5 <script setup> 6 import {onMounted, ref} from "vue"; 7 import * as THREE from "three"; 8 import ForceGraph3D from "3d-force-graph"; 9 10 const container = ref(null) 11 const imgs = ['cat.jpg', 'dog.jpg', 'eagle.jpg', 'elephant.jpg', 'grasshopper.jpg', 'octopus.jpg', 'owl.jpg', 'panda.jpg', 'squirrel.jpg', 'tiger.jpg', 'whale.jpg']; 12 const gData = { 13 nodes: imgs.map((img, id) => ({ id, img })), 14 links: [...Array(imgs.length).keys()] 15 .filter(id => id) 16 .map(id => ({ 17 source: id, 18 target: Math.round(Math.random() * (id-1)) 19 })) 20 } 21 22 onMounted(() => { 23 loadView() 24 }) 25 26 27 const loadView = () => { 28 ForceGraph3D()(container.value) 29 .nodeThreeObject(({ img }) => { 30 const imgTexture = new THREE.TextureLoader().load(require(`../assets/imgs/${img}`)) 31 imgTexture.colorSpace = THREE.SRGBColorSpace; 32 const material = new THREE.SpriteMaterial({ map: imgTexture }); 33 const sprite = new THREE.Sprite(material); 34 sprite.scale.set(12, 12); 35 return sprite; 36 }) 37 .graphData(gData); 38 } 39 40 </script>
代碼講解:(剛接觸講得不好請留言交流,謝謝)
1 nodes: imgs.map((img, id) => ({ id, img }))只要輸出一下nodes就能看出,它就是將imgs數組中的每個元素img和對應的索引包裝成一個對象,并返回一個新數組。
1 links: [...Array(imgs.length).keys()] 2 .filter(id => id) 3 .map(id => ({ 4 source: id, 5 target: Math.round(Math.random() * (id-1)) 6 }))
-
links: [...Array(imgs.length).keys()] 首先通過擴展運算符來解析ing數組,獲取每個圖片在數組中的索引。
-
filter(id => id) 采用過濾器,過濾掉數組中值為0的元素:作用一、排除了索引為0的元素;作用二、確保生成的鏈接對象不會以自連接的形式存在
-
3. map(id => ({ source: id, target: Math.round(Math.random() * (id-1)) })) 此操作是將過濾后的索引數組的每個元素進行執行,返回一個包含數組讓其每個對象都包含source(起點)、target(終點)兩個屬性。
- 重點來了
1 ForceGraph3D()(container.value) // 將一個 3D 力導向圖形繪制到 container 引用所指向的 DOM 元素上。 2 .nodeThreeObject(({ img }) => { // 在繪制力導向圖中的每個節點時,使用一個功能回調來定義節點的三維對象,接受一個參數 img 3 const imgTexture = new THREE.TextureLoader().load(require(`../assets/imgs/${img}`)) // 通過調用 THREE的TextureLoader的load方法來獲取靜態資源,此處有坑,下面細講 4 imgTexture.colorSpace = THREE.SRGBColorSpace; // THREE.SRGBColorSpace 是Three.js庫中的一個常量,它表示使用sRGB顏色空間。sRGB是一種在計算機圖形和顯示設備中廣泛使用的標準顏色空間。它提供了一種線性響應曲線,使得顏色在不同設備之間能夠更一致地顯示 5 const material = new THREE.SpriteMaterial({ map: imgTexture }); // 使用Three.js庫創建精靈(Sprite)材質的代碼片段。在Three.js中,精靈是一種在三維場景中以二維圖像的形式顯示的對象。此處創建了一個新的精靈材質,并使用名為
imgTexture的紋理貼圖作為精靈的材質 6 const sprite = new THREE.Sprite(material); // 使用之前創建的material作為精靈的材質,并通過new THREE.Sprite()創建一個新的精靈對象 7 sprite.scale.set(12, 12); //sprite是之前創建的精靈對象,set(12, 12)表示將精靈對象在x和y軸上的縮放比例設置為12 8 return sprite; // 最后將這個精靈返回給調用方 9 }) 10 .graphData(gData); // 加載數據 11 }
最重點的坑來了!!!
最重點的坑來了!!!
最重點的坑來了!!!
重要的事情說三遍
先來個小一點的問題:
在引入依賴時,最好自己引入,不要借助開發工具自動引入,我當時懶了,沒自己按規范引入,結果代碼運行起來就報了個錯誤:
import THREE from "three"; // 錯誤引入 import * as THREE from "three"; // 正確引入
Cannot read properties of undefined (reading 'TextureLoader')
TypeError: Cannot read properties of undefined (reading 'TextureLoader')

其次,重點的問題,別光照著官網文檔敲,需要動下腦子,我就呆了,沒有動腦子,結果在引入圖片的時候,完全照抄,怎么都引入不進去,還各種百度都說我讓我檢查路徑(采用相對路徑),結果發現是官網采用的是html里面js獲取靜態資源 和 我的vue獲取資源的方法有些出入,報的錯如下:

注意點:
const imgTexture = new THREE.TextureLoader().load(`../assets/imgs/${img}`) // 官網寫法 const imgTexture = new THREE.TextureLoader().load(require(`../assets/imgs/${img}`)) //vue中正確寫法,需要通過require獲取資源,比官網多了個require方法
這個案例就碰到這兩個問題,希望各位朋友多多留言交流技術,一起進步,謝謝
浙公網安備 33010602011771號