首先3d-force-graph在码云或者github直接搜索,它的文档确实有点少。这个插件用了3次,每一次都有不同的痛苦,也有粗心大意所导致的。
好的,我们现在讲解一下这个插件中的导向树DAG模式
我的案例都会基于Vue开发,创建项目等等我们进不说了,进入正题。
步骤:1.安装:npm i 3d-force-graph (我安装的是"3d-force-graph": “^1.67.5”,)
2.导入 import ForceGraph from ‘3d-force-graph’;
首先注意点:
1.不要全部cv我的代码,或者光放文档中的代码,我们要依据后台数据实际看问题,但是基本的代码步骤是差不多的,但是也不要全CV,不然你的浏览器会报错,而且你以为错误是你的逻辑问题,实际上是cv多了的问题(这一点使我耽误了半天的时间)
2. 数据处理设计到了递归等,数据接口我就不写了
在模板中定义:
import ForceGraph from '3d-force-graph'; // 导入
import { subjectList } from '../src/request/api'; // 掉数据的接口
data() {
return {
// 源数据
sourceData: null,
// 力导向图数据
nodes: [],
links: [],
ForceGraphData: {}
};
},
初始话完成
async created() {
// 获取数据接口
try {
const { data: res } = await subjectList();
this.sourceData = res.data;
console.log(this.sourceData);
} catch (err) {
console.log(err);
}
this.digui(this.sourceData); // 递归处理数据
this.SetForce(); // 调用力导向图
},
进入数据
methods: {
// 1.先定义数据
// 首先定义nodes数据;节点数据 设计递归定义方法
digui(data) {
data.children.forEach(item => {
if (item.children) {
this.digui(item);
}
const nodeObjs = {};
nodeObjs.name = item.name;
nodeObjs.id = item.id;
nodeObjs.level = item.level;
nodeObjs.parent_id = item.parent_id;
nodeObjs.has_children = item.has_children;
const linksObjs = {};
linksObjs.source = item.parent_id;
linksObjs.target = item.id;
this.nodes.push(nodeObjs);
this.links.push(linksObjs);
});
},
后端返回的数据是格式我们需要用递归地方法把他们处理
要知道插件的节点是nodes数据,连线是links数据,links数组中的每一项都有source和target,source的是连线的开始端,target是连线的结束端,source的是parent_id,target的是id,也就是依据数据进行连接,这一不懂的话可以看看这个插件的这个案例
好,继续,处理完的数据是nodes数据后端数据返回的每一项包括children下的每一项,links数据是每一项是的target:id和source:parent_id
处理数据完成,下一部在methods中设置力导向图的函数
// 设置力导向图
SetForce() {
// 这里在最想面插入了一条数据是因为后端返还的数据和依据插件的机制需要我在最前面插入一条最起点的数据
//也就是这条数据就是起源,一般来说你们也会在最前面插入一条起源数据,因为后端数据差不多样式都是一样的
// 这条数据就不用在添加parent_id了,就是返回的有parent_id,而不需要添加。
this.nodes.unshift({
id: 10515,
name: '化学',
level: 1,
});
this.ForceGraphData.links = this.links;
this.ForceGraphData.nodes = this.nodes;
const gukergForce = ForceGraph();
gukergForce(document.querySelector('.wrap'))
// 力导向图放在容器中 记住这个容器在样式中要给大小
.graphData(this.ForceGraphData)// 这条就是数据源
.dagMode('td') // 模式有很多选择,我选择的td,自上而下的格式,文档中有选择,你们按自己需求选
}
},
现在一个简单的力导向树就出来了,随项目的需求你可在节点加图片,你需要import * as THREE from ‘three’;这个包不用下载,直接导入就可以,
const gukergForce = ForceGraph(); // 力导向图放在容器中
gukergForce(document.querySelector('.wrap'))
.graphData(this.ForceGraphData)
.dagLevelDistance(70) // 两点直接的距离
.dagMode('td')
.nodeResolution(50) // 较高的值产生较光滑的球体。
.nodeThreeObject(node => {
.nodeThreeObject(node => {
if (node.level === 1) {
console.log('你好');
}
let imgTexture = '';
if (node.level === 1) {
imgTexture = new THREE.TextureLoader().load(require('./assets/1.png'));
} else if (node.level === 2) {
imgTexture = new THREE.TextureLoader().load(require('./assets/2.png'));
} else if (node.level === 3) {
imgTexture = new THREE.TextureLoader().load(require('./assets/3.png'));
} else if (node.level === 4) {
imgTexture = new THREE.TextureLoader().load(require('./assets/4.png'));
} else if (node.level === 5) {
imgTexture = new THREE.TextureLoader().load(require('./assets/5.png'));
}
const material = new THREE.SpriteMaterial({ map: imgTexture });
const sprite = new THREE.Sprite(material);
if (node.level === 1) {
sprite.scale.set(50, 45);
return sprite;
} else if (node.level === 2) {
sprite.scale.set(20, 20);
return sprite;
}
if (node.level === 3) {
sprite.scale.set(30, 30);
return sprite;
}
if (node.level === 4) {
sprite.scale.set(20, 15);
return sprite;
}
if (node.level === 5) {
sprite.scale.set(20, 20);
return sprite;
}
});
}
其实由谁解决了它节点之间不重复的问题,可以给我留言,谢谢