vue3 中 练习 3d-force-graph 中 img-nodes项目

  1. 首先要搞清楚需要的那些功能的插件是哪些
  2. 引入插件 three.js 和 3d-force-graph
    1 import * as THREE from "three";
    2 import ForceGraph3D from "3d-force-graph";
  3. 最基础的:声明一个div容器渲染页面使用
    1 <template>
    2 <div ref="container"></div>
    3 </template>

    注:在vue3中的setup语法糖推荐使用ref在组建中创建一个可响应式的引用,通过ref可以轻松访问要操作的DOM,同时在script中创建一个container的引用,并将ref函数初始化为null,代码如下:

    1 const container = ref(null)
  4. 先上代码
     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       }))
    1. links: [...Array(imgs.length).keys()] 首先通过扩展运算符来解析ing数组,获取每个图片在数组中的索引。
    2. 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方法

 

这个案例就碰到这两个问题,希望各位朋友多多留言交流技术,一起进步,谢谢

 

posted @ 2023-07-08 00:18  小杨同学906  阅读(315)  评论(0)    收藏  举报