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号