echarts画桑基图,并根据选择的分析因子画图
最近要在系统中增加一个桑基图,要求桑基图可以根据选择的分析因子重新绘图。仔细看了下 echarts 的示例,桑基图本身很简单,困难的是如何根据数据资料整理成桑基图的数据格式,并且实现选择分析因子重新绘图。研究了几天的数据资料,特将方法写个 demo 记录下。
<script src="./plugins/echarts.min.js"></script>
<div>
<label><input type="checkbox" name="factor" value="city" />city</label>
<label><input type="checkbox" name="factor" value="degree" />degree</label>
<label><input type="checkbox" name="factor" value="type" />type</label>
<button onclick="handleSankeyChart()">确定</button>
</div>
<div id="main3" style="height: 400px"></div>
<script>
const data_orig = [
{ city: "北京", degree: "本科", value: 300, type: "减少" },
{ city: "广州", degree: "硕士", value: 400, type: "增加" },
{ city: "深圳", degree: "硕士", value: 360, type: "增加" },
{ city: "北京", degree: "硕士", value: 250, type: "减少" },
{ city: "上海", degree: "本科", value: 350, type: "减少" },
{ city: "重庆", degree: "本科", value: 300, type: "增加" },
{ city: "深圳", degree: "本科", value: 230, type: "增加" },
];
//统计数据
const data = {};
for (let i in data_orig) {
const key_arr = [];
for (let key in data_orig[i]) {
if (key != "value") {
key_arr.push(data_orig[i][key]);
}
}
const key_str = key_arr.join("|");
if (!(key_str in data)) data[key_str] = 0;
data[key_str] += data_orig[i]["value"];
}
//数据key中分析因子的顺序,后面可根据此顺序获取对应的值
const key_order = ["city", "degree", "type"];
function handleSankeyChart() {
const params = [];
document.querySelectorAll("input[name=factor]").forEach((e, i) => {
if (e.checked) params.push(e.value);
});
const data_links_all = [];
for (let key in data) {
const key_arr = key.split("|");
for (let i = 1; i < params.length; i++) {
const order_index = key_order.indexOf(params[i]);
const target = key_arr[order_index];
const source = key_arr[key_order.indexOf(params[i - 1])];
data_links_all.push({
source: source,
target: target,
value: data[key],
});
}
}
//links 去掉source=target的项(会报错),合并source和target分别相同的项
const data_links = [];
const pairs = [];
for (let i in data_links_all) {
const key = data_links_all[i]["source"] + "|" + data_links_all[i]["target"];
const index = pairs.indexOf(key);
if (index == -1 && data_links_all[i]["source"] != data_links_all[i]["target"]) {
pairs.push(key);
data_links.push(data_links_all[i]);
} else if (data_links_all[i]["source"] != data_links_all[i]["target"]) {
data_links[index]["value"] += data_links_all[i]["value"];
}
}
//根据links,组装节点数据
const data_nodes = [];
const items = [];
if (data_links.length > 0) {
for (let i in data_links) {
if (items.indexOf(data_links[i]["source"]) === -1) {
data_nodes.push({
name: data_links[i]["source"],
});
items.push(data_links[i]["source"]);
}
if (items.indexOf(data_links[i]["target"]) === -1) {
data_nodes.push({
name: data_links[i]["target"],
});
items.push(data_links[i]["target"]);
}
}
}
drawSankeyChart(data_nodes, data_links);
}
function drawSankeyChart(data_nodes, data_links) {
var chartDom = document.getElementById("main3");
var myChart = echarts.init(chartDom);
var option;
option = {
tooltip: {
trigger: "item",
triggerOn: "mousemove",
},
series: [
{
type: "sankey",
//严格按照数据节点的顺序显示
layoutIterations: 0,
emphasis: {
focus: "series",
},
//定义文本宽度及超出后的换行
label: {
width: 100,
overflow: "break",
},
data: data_nodes,
links: data_links,
},
],
};
option && myChart.setOption(option);
}
</script>
实现了如下的效果:



当桑基图中 layoutIterations 配置项取默认的值 32 时,echarts 会优化图形的显示,减少连线交叉

浙公网安备 33010602011771号