Sankey диаграмма визуализирует потоки между различными категориями/состояниями, показывая, как значения распределяются между этапами, частями или группами. Ширина каждого связи ("потока") пропорциональна величине или количеству переданного ресурса — денег, энергии, пользователей и т.п.
Области применения:
Анализ движения ресурсов, финансов или пользователей между этапами процесса Разложение расходов, бюджетов, цепочек поставок Отслеживание переходов между статусами/категориями
Для построения Sankey в ECharts нужны:
nodes — массив уникальных объектов, каждый с идентификатором (name), отражает все возможные категории и промежуточные узлы; links — массив связей, каждая связь — это объект { source, target, value }, где: source — имя узла-отправителя (строка, должен быть в nodes), target — имя узла-получателя (строка, должен быть в nodes), value — числовое значение потока.
Пример диаграммы для отображения перехода продаж в прибыль по различным категориям продуктов.
Оператор данных:
function dataCal(originData) {
var dataModels = originData.dataModels;
var colData = dataModels[0].colData;
var data = [];
for (var i = 0; i < colData[0].length; i++) {
data[i] = {
product: colData[0][i],
profit: colData[1][i],
sales: colData[2][i]
};
}
return data;
}Оператор конфигураций:
function optionCal(data, chartConfig, chart) {
var products = [];
data.forEach(function(item) {
if (products.indexOf(item.product) === -1) products.push(item.product);
});
// Узлы: Продажи, каждый продукт, Прибыль
var nodes = [{ name: 'Продажи' }]
.concat(products.map(function(p) { return { name: p }; }))
.concat([{ name: 'Прибыль' }]);
// Связи: Продажи -> продукт, продукт -> Прибыль
var links = [];
data.forEach(function(item) {
links.push({ source: 'Продажи', target: item.product, value: Number(item.sales) });
links.push({ source: item.product, target: 'Прибыль', value: Number(item.profit) });
});
return {
title: { text: 'Sankey Chart Example', left: 'center' },
tooltip: { trigger: 'item' },
series: [{
type: 'sankey',
data: nodes,
links: links,
top: 40,
focusNodeAdjacency: true,
label: { fontSize: 14 }
}]
};
}