目录
- 什么是桑基图
- 桑基图的特点及应用场景
- Echarts中桑基图的常用属性
- Vue3中创建桑基图
- 美化桑基图
在各种复杂系统中,我们经常需要了解不同流量之间的关系和流动情况。这种信息的可视化呈现对于我们理解系统的结构和转移过程至关重要。桑基图作为一种强大的可视化工具,能够直观地展示不同流量之间的相对大小和流动路径。
什么是桑基图
桑基图(Sankey)是一种图表形式,用于展示不同流量之间的关系和流动情况,如用来表示原材料、能量等如何从最初形式经过中间过程的加工或转化达到最终状态。它由一系列有向箭头连接的节点组成,每个节点表示一个流量的起点或终点,箭头的宽度表示流量的大小。桑基图常用于描述能源流动、物质流动、资金流动等复杂系统中的关系和转移情况。通过桑基图,人们可以直观地了解不同流量之间的相对大小和流动路径,从而帮助分析和决策。
桑基图的特点及应用场景
桑基图具有以下几个特点,使其成为数据可视化中的重要工具:
-
直观易懂:桑基图通过箭头的宽度和节点之间的连接关系,直观地展示了不同流量之间的大小和流动情况,使复杂的数据更易于理解。
-
多维度展示:桑基图可以同时展示多个维度的数据,例如起点、终点、流量大小等,帮助我们全面了解系统的转移过程。
-
可视化分析:通过桑基图,我们可以快速发现流量的瓶颈、转移路径以及关键节点,从而进行数据分析和决策。
-
应对大数据:桑基图适用于大规模的数据集,能够处理大量的节点和边,为我们提供全局的数据视角。
桑基图在许多领域都有广泛的应用,包括能源管理、物流分析、财务规划、人口迁移等。例如,能源流动的桑基图可以帮助分析能源结构和优化能源配置,物流分析中的桑基图可以揭示货物的流向和转移路径,人口迁移的桑基图可以帮助了解不同地区之间的人口流动情况。桑基图的应用场景非常丰富,只要涉及到流动关系的问题,都可以考虑使用桑基图进行可视化分析。
Echarts中桑基图的常用属性
type
:指定图表的类型为sankey
,表示创建一个桑基图。data
:表示节点的数据,每个节点通过name
属性指定名称。可以进一步设置其它属性,如itemStyle
用于设置节点的样式。links
:表示边的数据,每条边通过source
和target
属性指定起点和终点,value
属性表示流量大小,可以进一步设置其它属性,如lineStyle
用于设置边的样式。lineStyle
:表示边的样式,可以设置颜色、透明度、曲线度等属性。label
:表示标签的样式,可以设置位置、颜色等属性。emphasis
:表示强调样式,可以设置焦点效果、边框样式等属性。layoutIterations
:指定布局迭代的次数,目的是不断迭代优化图中节点和边的位置,以减少节点和边之间的相互遮盖,默认为32。可以调整此属性来改变桑基图的布局效果。orient
:指定节点的排列方向,可选值为horizontal
(水平)和vertical
(垂直)。通过调整此属性,可以改变桑基图节点的排列方式。nodeWidth
:指定桑基图中每个矩形节点的宽度,默认为20。可以调整此属性来改变节点的宽度大小。nodeGap
:指定桑基图中每一列任意两个矩形节点之间的间隔,默认为8。可以调整此属性来改变节点之间的间距大小。draggable
:控制节点拖拽的交互,默认开启。开启后,用户可以将图中任意节点拖拽到任意位置。若想关闭此交互,只需将值设为false
就行了。animation
:指定是否启用动画效果,默认为true
。可以将此属性设置为false
,禁用桑基图的动画效果。
Vue3中创建桑基图
- 创建vue项目,安装ECharts库
npm install echarts --save
- 新建SankeyView.vue文件,使用
import
语句引入ECharts库
import * as echarts from 'echarts';
- 创建图表容器:在SankeyView组件的
template
中,添加一个div
元素作为图表的容器。给它一个唯一的ref
属性,以便在后面初始化图表对象时使用
<template>
<div ref="chart" style="width: 100%;height: 400px;"></div>
</template>
- 初始化图表对象:在SankeyView组件中定义chart,
const chart = ref(null)
在mounted
生命周期钩子函数中,使用echarts.init
方法初始化图表对象。
<script setup>
import { ref, onMounted } from 'vue'
import * as echarts from 'echarts'
const chart = ref(null)
onMounted(() => {
const myChart = echarts.init(chart.value)
})
</script>
- 准备数据,实际项目中,数据是通过接口从后台获取的,这里只是作为演示,数据定义在前端
const data = [
{ source: '北京', target: '上海', value: 1000 },
{ source: '北京', target: '广州', value: 500 },
{ source: '上海', target: '杭州', value: 800 },
{ source: '上海', target: '深圳', value: 700 },
{ source: '广州', target: '深圳', value: 300 },
{ source: '杭州', target: '苏州', value: 600 },
{ source: '杭州', target: '南京', value: 400 },
{ source: '深圳', target: '珠海', value: 200 },
{ source: '苏州', target: '无锡', value: 300 },
{ source: '南京', target: '合肥', value: 200 },
{ source: '珠海', target: '澳门', value: 100 },
];
上面代码中,定义变量data用于包含桑基图数据的数组。data中的每个元素包含两个属性,即source和target,分别表示数据的源节点和目标节点。
6. 对上面的数据进行处理,使其符合桑基图的数据格式
const nodes = Array.from(new Set([...data.map(d => d.source), ...data.map(d => d.target)]));
上面这段代码的目的是提取出桑基图数据中所有的源节点和目标节点,并将它们存储在一个没有重复元素的数组中,以便后续处理和使用。
代码中使用Array.from()方法结合Set数据结构实现去重操作。
首先,通过映射函数d => d.source将data中的每个元素的source属性取出,并通过映射函数d => d.target将data中的每个元素的target属性取出。然后,将这两个结果数组使用展开运算符…合并为一个新的数组,该数组包含了所有的源节点和目标节点。
接下来,通过Set构造函数将新数组转换为一个Set实例,Set实例会自动剔除重复的元素。最后,将Set实例再次转换为数组,即可得到一个包含所有唯一节点的nodes数组。
- 配置图表参数,在SankeyView组件的
mounted
生命周期钩子函数中,定义option对象,在里面配置图表数据,并使用chart.setOption
方法配置图表的参数。
onMounted(() => {
const myChart = echarts.init(chart.value)
const option = {
title: {
text: '人口迁移桑基图',
left: 'center',
textStyle: {
color: '#333',
fontSize: 20,
fontWeight: 'bold',
},
},
tooltip: {
trigger: 'item',
triggerOn: 'mousemove',
},
series: [
{
type: 'sankey',
data: nodes.map(n => ({ name: n })),
links: data.map(d => ({ source: d.source, target: d.target, value: d.value })),
lineStyle: {
opacity: 0.5,
curveness: 0.3,
},
label: {
position: 'right',
color: '#000',
},
emphasis: {
focus: 'adjacency',
itemStyle: {
borderWidth: 2,
borderColor: '#333',
},
},
},
],
}
myChart.setOption(option)
})
一个桑基图就创建好了,刷新浏览器,看下效果
美化桑基图
上面的桑基图颜色比较单一,我们可以通过修改lineStyle属性来设置各个节点数据流向的颜色。
首先我们定义一个颜色数组
const colors = ['#4fb9d1', '#d83965', '#f39c38', '#9036aa', '#4054af', '#e35241', '#3f9488', '#97c05c', '#154bee', '#33e6cc', '#123997', '#faa200', '#ffff00', '#b0e0e6', '#470024', '#bce700', '#4396ec']
在links配置项中,我们给data.map的回调函数添加index索引,通过遍历数据数组 data,为每条边设置不同的线条样式,在样条样式中设置颜色配置项
links: data.map((d, index) => ({
source: d.source,
target: d.target,
value: d.value,
lineStyle: {
color: colors[index % colors.length], // 使用颜色数组中的颜色设置线条颜色
},
上述代码中,data.map((d, index) => { … }) 遍历 data 数组,并为每个元素执行回调函数。
在回调函数中,我们使用当前元素的索引 index 来获取对应的颜色。
colors 是前面定义的一个颜色数组,包含了多个颜色值。
index % colors.length 通过取模运算将索引值限制在颜色调色板数组的长度范围内。这样可以确保当索引超过颜色调色板长度时,仍能循环使用颜色。
lineStyle 对象用于设置线条的样式,其中的 color 属性被设置为 colors[index % colors.length],即根据索引使用颜色调色板中的对应颜色值。
刷新浏览器看效果
OK,关于桑基图的介绍就到这里吧,喜欢的小伙伴点赞关注收藏哦,也可以通过微信公众号搜索“九仞山”,获取更多内容。