需求描述
把一類錯綜復雜的知識點按照相關性規則連線,客觀匯總展現出來,切換類型可動態刷新圖譜,圖譜節點能點擊交互。
實現效果
實現思路
先格式化處理后台拿到的數據,再利用Echarts 的 graph 類型圖庫進行配置繪制。
代碼實現
先用mock造個數據實現接口,其中圖譜數據中的 name就是節點展示的內容,category 可以作為過濾條件給節點設置不同的顏色,若要設置特殊大小可以symbolSize設值, id是用來前后連線的標識。
/**
* 圖譜數據源源
*/
export const data = [
{
id:1,
name:'測試節點',
categary:'1',
symbolSize: 60
},
{
id:2,
name:'測試節點',
categary:'1',
symbolSize: 40
},
{
id:3,
name:'測試節點',
categary:'2',
},
{
id:4,
name:'測試節點',
categary:'',
},
{
id:5,
name:'測試節點測試節點',
categary:'',
},
{
id:6,
name:'測試節點',
categary:'2',
},
{
id:7,
name:'測試節點',
categary:'',
},
{
id:8,
name:'測試節點',
categary:'',
},
{
id:9,
name:'測試節點',
categary:'',
},
{
id:10,
name:'測試節點',
categary:'',測試節點
}
];
//節點連線
let linkData = [
{source: '2', target: '3', name: ''},
{source: '3', target: '4', name: ''},
{source: '3', target: '5', name: ''},
{source: '5', target: '6', name: ''},
{source: '5', target: '7', name: ''},
{source: '5', target: '8', name: ''},
{source: '9', target: '10', name: ''},
{source: '10', target: '9', name: ''},
{source: '1', target: '2' , name: ''},
{source: '1', target: '10', name: ''}
]
/**
* 模糊查詢大類
* @param {*} name
*/
export const search = (name)=>{
return new Promise((resolve,reject)=>{
let result = {
seriesData: [],
linksData: []
}
let list = data.filter(item=>item.name.indexOf(name)>=0)
if(list&&list.length>0){
result.seriesData = list ||[];
}else{
result.seriesData = data ||[];
}
result.linksData = linkData ||[];
if(list.length>0){
resolve(result)
}else{
reject()
}
})
}
export const getAllData = ()=>{
return new Promise((resolve,reject)=>{
let result = {
seriesData: [],
linksData: []
}
result.seriesData = data||[];
result.linksData = linkData ||[];
if(data.length>0){
resolve(result)
}else{
reject()
}
})
}
/**
* 分類2
*/
export const categarys = ["建設用地"]
封裝一個chart組件,實現圖譜展示
<template>
<div id="chart" class="chart"></div>
</template>
<script>
import { expendNodes } from "./mock";
var echarts = require("echarts/lib/echarts");
require("echarts/lib/chart/graph");
require("echarts/lib/component/tooltip");
require("echarts/lib/component/title");
export default {
name: "Charts",
props: {
chartList: {
type: Object,
required: true,
},
},
watch: {
chartList: {
handler(val) {
this.formatData(val || [], true);
},
},
},
data() {
return {
myChart: "",
seriesData: [],
seriesLinks: [],
categories:[],
lastClickId: "",
colors: ["#a3d2ca","#056676","#ea2c62","#16a596","#03c4a1","#f5a25d",
"#8CD282","#32e0c4","#00FAE1","#f05454"],
};
},
methods: {
/**
* 節點點擊事件
*/
async nodeClick(params) {
const index = this.seriesData.findIndex(
(item) => item.id === params.data.id
);
console.log('點了節點:'+index+1,"clicked");
},
/**
* 設置echarts配置項,重繪畫布
*/
initCharts() {
const that = this;
if (!this.myChart) {
this.myChart = echarts.init(document.getElementById("chart"));
this.myChart.on("click", (params) => {
if (params.dataType === "node") {
//判斷點擊的是圖表的節點部分
this.nodeClick(params);
}
});
}
// 指定圖表的配置項和數據
let option = {
// 動畫更新變化時間
animationDurationUpdate: 500,
animationEasingUpdate: "quinticInOut",
tooltip: {
show: false,
},
series: [
{
type: "graph",
layout: "force",
legendHoverLink: true, //是否啟用圖例 hover(懸停) 時的聯動高亮。
hoverAnimation: true, //是否開啟鼠標懸停節點的顯示動畫
focusNodeAdjacency: true,
edgeLabel: {
position: "middle", //邊上的文字樣式
normal: {
show: true,
textStyle: {
fontSize: 12,
},
position: "middle",
formatter: function (x) {
return x.data.name;
},
},
},
edgeSymbol: ["", "arrow"],
force: {
edgeLength: 15,
repulsion: 200,
},
roam: true,
draggable: true, //每個節點的拖拉
itemStyle: {
normal: {
color: "#00FAE1",
cursor: "pointer",
//color:Math.floor(Math.random()*16777215).toString(16),
//color: ['#fc853e','#28cad8','#9564bf','#bd407e','#28cad8','#fc853e','#e5a214'],
label: {
show: true,
position: [-10, -15],
textStyle: {
//標簽的字體樣式
color: "#fff", //字體顏色
fontStyle: "normal", //文字字體的風格 'normal'標准 'italic'斜體 'oblique' 傾斜
fontWeight: "bold", //'normal'標准'bold'粗的'bolder'更粗的'lighter'更細的或100 | 200 | 300 | 400...
fontFamily: "sans-serif", //文字的字體系列
fontSize: 12, //字體大小
},
},
nodeStyle: {
brushType: "both",
borderColor: "rgba(255,215,0,0.4)",
borderWidth: 1,
},
},
//鼠標放上去有陰影效果
emphasis: {
shadowColor: "#00FAE1",
shadowOffsetX: 0,
shadowOffsetY: 0,
shadowBlur: 40,
},
},
lineStyle: {
width: 2,
},
label: {
fontSize: 18,
},
symbolSize: 24, //節點大小
links: this.seriesLinks,
data: this.seriesData,
categories:this.categories,
cursor: "pointer",
},
],
};
// 使用剛指定的配置項和數據顯示圖表。
this.myChart.setOption(option);
},
/**
* 格式化數據到表格需要的數據
*/
formatData(list, reset = false) {
const that =this;
let nodes = list.seriesData;
this.seriesData = [];
this.seriesLinks = [];
let colorIndex = 0;
let data =[];
let loadedCat=[];
nodes.forEach((item,index)=>{
if(item.categary && loadedCat.indexOf(item.categary) === -1){
colorIndex = Math.floor((Math.random()*that.colors.length));
loadedCat.push(item.categary);
this.categories.push({name:item.categary});
}
item.itemStyle = {
color: that.colors[colorIndex],
borderColor: '#ffffff'
}
data.push(item);
})
this.seriesData.push(...data);
this.seriesLinks.push(...list.linksData);
this.initCharts();
},
},
beforeDestroy() {},
};
</script>
<style scoped>
.chart {
height: 100%;
}
</style>
在其他組件中調用chart組件,並傳入展示的數據內容
<Charts ref="charts" v-show="type === 2" :chartList="searchList" />
完畢!