ECharts 的 graph
图表类型非常适合用来展示节点之间的关系,比如社交网络分析、系统架构图等。下面是一个简单的关系图功能,用来展示疾病与一些因素的关联关系。
1、数据之间的关系
首先,你需要准备数据来表示节点(nodes)和它们之间的边(links)。节点通常包括节点的名称或 ID,而边则包含两个节点之间的连接信息。
var data = {
nodes: [
{
name: '疾病名称',
symbolSize: [100, 100],
itemStyle: {
color: '#C280FF',
borderColor: '#000'
},
value: '123456'
}, {
name: '食物1',
symbolSize: [80, 80],
itemStyle: {
color: '#CAF982'
},
value: '123457'
}, {
name: '化合物1',
symbolSize: [80, 80],
itemStyle: {
color: '#FACD91'
},
value: '123458'
}, {
name: '生活方式1',
symbolSize: [80, 80],
itemStyle: {
color: '#FFFF80'
},
value: '123459'
}, {
name: '膳食模式1',
symbolSize: [80, 80],
itemStyle: {
color: '#80FFFF'
},
value: '1234510'
}
],
links: [
{
target: '食物1',
source: '疾病名称',
category: 'Food'
}, {
target: '化合物1',
source: '疾病名称',
category: 'Compound'
}, {
target: '生活方式1',
source: '疾病名称',
category: 'lifestyle'
}, {
target: '膳食模式1',
source: '疾病名称',
category: 'dietary_pattern'
}
]
};
通过仔细观察你会发现,nodes
里面的数组存放的是将要展示倒关系图中的节点数据,links里面的数组存放的是,节点直接的联系。在我这个功能里,nodes
的第一个节点元素是中间节点,其他节点要以它为中心进行环形分布。links
中节点的target属性表示指向那个node
节点,source
表示将要围绕的节点,category
是节点的分类,在下面的操作中我们将根据这个属性找到节点关系饼图的数据。
2、点击事件
chartClick (params) {
console.log('click', params)
if (params.componentType === 'series') {
if (params.seriesType === 'graph') {
if (params.dataType === 'edge') {
// 点击到了 graph 的 edge(边)上。
console.log('点击到了 graph 的 edge(边)上')
this.showLinkModal(params)
} else {
// 点击到了 graph 的 node(节点)上。
console.log('点击到了 graph 的 node(节点)上')
if (params.dataIndex > 0) {
this.showNodeModal(params)
}
}
}
}
}
通过click
事件执行一个回调函数,就可以拿到我们想要的信息,然后去执行一些业务操作。
this.myChart.on('click', function (params) {
_this.$emit('chartClick', params)
})
3、echarts 组件模板
<template>
<div
:ref="`echartsComponent${random}`"
:style="{ width: width, 'height': height }"
></div>
</template>
<script>
import { createRandomId } from '@/libs'
import * as echarts from 'echarts'
export default {
computed: {
random: function () {
return createRandomId()
}
},
props: {
width: {
default: '100%',
type: String
},
height: {
default: '100px',
type: String
}
},
data () {
return {
myChart: null
}
},
mounted () {
},
methods: {
initData (data) {
const _this = this
this.$nextTick(() => {
this.myChart = echarts.init(this.$refs[`echartsComponent${this.random}`])
this.myChart.setOption(data)
this.myChart.on('click', function (params) {
_this.$emit('chartClick', params)
})
})
},
disposeCharts () {
this.myChart.dispose()
},
resetData (data) {
this.myChart.setOption(data)
}
}
}
</script>
4、简单关系图示例
<template>
<Modal
v-model="visible"
:title="title"
width="1000"
footer-hide
@on-cancel="cancel"
>
<echarts-item ref="graphChart" height="900px" @chartClick="chartClick" />
<node-modal ref="nodeModalRef" />
<link-modal ref="linkModalRef" />
</Modal>
</template>
<script>
import EchartsItem from '@/components/EchartsItem'
import NodeModal from './NodeModal'
import LinkModal from './LinkModal'
export default {
components: {
EchartsItem,
NodeModal,
LinkModal
},
data () {
return {
title: '',
visible: false,
// 关系图数据
nodeData: [],
chartData: []
}
},
methods: {
init (nodeData, options) {
this.visible = true
this.nodeData = nodeData
this.$nextTick(() => {
this.initChart(options)
})
},
cancel () {
this.visible = false
this.$refs.nodeModalRef.cancel()
this.$refs.linkModalRef.cancel()
},
initChart () {
const options = {
title: '',
tooltip: {
show: false
},
legend: {
show: false
},
xAxis: {
show: false
},
yAxis: {
show: false
},
series: [{
type: 'graph',
roam: true,
focusNodeAdjacency: true,
force: {
// 节点之间的斥力因子
repulsion: 1400,
// 边的两个节点之间的距离
edgeLength: [300, 350]
},
layout: 'force',
symbol: 'circle',
// 图形是否不响应和触发鼠标事件,默认为 false,即响应和触发鼠标事件。
// silent: true,
// 是否开启动画
animation: false,
itemStyle: {
borderColor: '#333'
},
lineStyle: {
color: '#333',
width: 2,
type: 'solid',
opacity: 0.5,
// curveness: 0.5
},
label: {
show: true,
position: 'inside',
textStyle: {
fontSize: 16
}
},
// 关系线上的lable
edgeLabel: {
normal: {
show: false,
textStyle: {},
formatter: function (param) {
return param.data.category
}
}
},
data: [{
name: '疾病名称',
symbolSize: [100, 100],
itemStyle: {
color: '#C280FF',
borderColor: '#000'
},
value: '123456'
}, {
name: '食物1',
symbolSize: [80, 80],
itemStyle: {
color: '#CAF982'
},
value: '123457'
}, {
name: '化合物1',
symbolSize: [80, 80],
itemStyle: {
color: '#FACD91'
},
value: '123458'
}, {
name: '生活方式1',
symbolSize: [80, 80],
itemStyle: {
color: '#FFFF80'
},
value: '123459'
}, {
name: '膳食模式1',
symbolSize: [80, 80],
itemStyle: {
color: '#80FFFF'
},
value: '1234510'
}],
// 节点间的关系数据
links: [{
target: '食物1',
source: '疾病名称',
category: 'Food'
}, {
target: '化合物1',
source: '疾病名称',
category: 'Compound'
}, {
target: '生活方式1',
source: '疾病名称',
category: 'lifestyle'
}, {
target: '膳食模式1',
source: '疾病名称',
category: 'dietary_pattern'
}]
}]
}
this.$refs.graphChart.initData(options)
},
chartClick (params) {
console.log('click', params)
if (params.componentType === 'series') {
if (params.seriesType === 'graph') {
if (params.dataType === 'edge') {
// 点击到了 graph 的 edge(边)上。
console.log('点击到了 graph 的 edge(边)上')
this.showLinkModal(params)
} else {
// 点击到了 graph 的 node(节点)上。
console.log('点击到了 graph 的 node(节点)上')
if (params.dataIndex > 0) {
this.showNodeModal(params)
}
}
}
}
},
showNodeModal (params) {
const node = this.nodeData[params.dataIndex - 1]
const options = {
legend: {
icon: 'circle',
left: 'center',
bottom: '5%',
itemWidth: 10
},
label: {
formatter: '{c}'
},
color: ['#6395fa','#f56e53','#fbb120'],
series: [
{
name: 'Access From',
type: 'pie',
radius: '50%',
center: ['50%', '40%'],
data: [
{ value: 1048, name: 'Positive' },
{ value: 735, name: 'Negative' },
{ value: 580, name: 'Relative' }
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
}
// 食物和化合物的时候显示
if (node.category === 'Disease' || node.category === 'Food' || node.category === 'Compound') {
this.$refs.nodeModalRef.init(node.name, node.category, options, node.showType)
}
},
showLinkModal (params) {
const infoList = [
{
category: 'Ariticles',
list: [
{
id: 1,
title: 'The optimal ratio of fat-to-carbohydrate in the diet.'
},
{
id: 2,
title: 'The hypobetalipoproteinemias.'
}
]
},
{
category: 'Clinical Trials',
list: [
{
id: 3,
title: 'Microbiota, Metabolome and Nutrition: an \'Artificially Intelligent\' Way to Personalized Nutrition'
}
]
}
]
this.$refs.linkModalRef.init(infoList)
}
}
}
</script>
你可以根据需要调整各种配置项来改善图表的外观和交互性。例如,改变颜色方案、增加更多动画效果等。
总结
以上就是一个简单的使用 ECharts 绘制关系图的例子。