您现在的位置是:网站首页 > 桑基图(Sankey)实现文章详情

桑基图(Sankey)实现

桑基图(Sankey)实现

桑基图是一种流图,用于展示能量、物质或成本在不同节点间的流动情况。ECharts提供了强大的桑基图支持,能够直观呈现复杂系统中的流量分配与转化关系。下面从基础配置到高级应用全面解析ECharts桑基图的实现方法。

基础配置

最简单的桑基图需要定义nodes和links两个核心数据项。nodes表示图中的节点,links表示节点间的流向关系。以下是一个基础示例:

option = {
  series: [{
    type: 'sankey',
    layout: 'none',
    data: [
      { name: 'A' },
      { name: 'B' },
      { name: 'C' },
      { name: 'D' }
    ],
    links: [
      { source: 'A', target: 'B', value: 10 },
      { source: 'A', target: 'C', value: 5 },
      { source: 'B', target: 'D', value: 8 },
      { source: 'C', target: 'D', value: 4 }
    ]
  }]
};

这段代码创建了四个节点(A/B/C/D)和四条连接线。value属性决定了线条的宽度,数值越大线条越粗。layout参数保持默认'none'即可,ECharts会自动计算节点位置。

样式定制

ECharts桑基图支持多层次的样式定制:

节点样式

series: [{
  type: 'sankey',
  nodeWidth: 20,  // 节点矩形宽度
  nodeGap: 10,    // 节点纵向间距
  nodeAlign: 'justify', // 节点对齐方式
  draggable: true, // 允许拖拽节点
  label: {
    color: '#333',
    fontSize: 12,
    position: 'right' // 标签显示位置
  },
  itemStyle: {
    borderWidth: 1,
    borderColor: '#aaa'
  }
}]

连线样式

series: [{
  type: 'sankey',
  lineStyle: {
    color: 'source', // 跟随源节点颜色
    curveness: 0.5,   // 连线曲度
    opacity: 0.8
  },
  emphasis: {  // 高亮样式
    lineStyle: {
      shadowBlur: 10,
      shadowColor: 'rgba(0,0,0,0.5)'
    }
  }
}]

数据动态更新

桑基图支持动态数据更新,这在展示随时间变化的流量时非常有用:

function updateChart() {
  const newNodes = generateRandomNodes();
  const newLinks = generateRandomLinks(newNodes);
  
  myChart.setOption({
    series: [{
      data: newNodes,
      links: newLinks
    }]
  });
}

// 每2秒更新一次
setInterval(updateChart, 2000);

多层桑基图

对于复杂的业务流程,可以构建多层桑基图:

const nodes = [
  { name: '原料采购', depth: 0 },
  { name: '生产加工', depth: 1 },
  { name: '质检', depth: 2 },
  { name: '仓储', depth: 3 },
  { name: '物流', depth: 4 },
  { name: '零售', depth: 5 }
];

const links = [
  { source: '原料采购', target: '生产加工', value: 100 },
  { source: '生产加工', target: '质检', value: 95 },
  { source: '质检', target: '仓储', value: 90 },
  { source: '仓储', target: '物流', value: 88 },
  { source: '物流', target: '零售', value: 85 }
];

通过为节点添加depth属性,可以控制节点的层级位置,构建出清晰的流程视图。

交互功能增强

ECharts桑基图支持丰富的交互功能:

myChart.on('click', function(params) {
  if (params.dataType === 'node') {
    console.log('点击节点:', params.name);
  } else if (params.dataType === 'edge') {
    console.log(`点击连线: ${params.data.source} -> ${params.data.target}`);
  }
});

// 添加图例交互
legend: {
  data: ['类别1', '类别2'],
  selectedMode: 'single',
  selected: {
    '类别1': true,
    '类别2': false
  }
}

大数据量优化

当处理大规模数据时,需要进行性能优化:

series: [{
  type: 'sankey',
  layoutIterations: 0, // 减少布局计算次数
  nodeWidth: 8,       // 减小节点宽度
  nodeGap: 6,         // 减小节点间距
  focusNodeAdjacency: false, // 关闭相邻高亮
  silent: true,       // 关闭交互事件
  progressive: 200,   // 渐进式渲染
  animation: false    // 关闭动画
}]

实际应用案例

能源流动分析

const energyNodes = [
  { name: '煤炭', itemStyle: { color: '#333' }},
  { name: '石油', itemStyle: { color: '#8B0000' }},
  { name: '天然气', itemStyle: { color: '#4682B4' }},
  { name: '发电', itemStyle: { color: '#FFA500' }},
  { name: '工业', itemStyle: { color: '#808080' }},
  { name: '居民', itemStyle: { color: '#228B22' }}
];

const energyLinks = [
  { source: '煤炭', target: '发电', value: 45 },
  { source: '石油', target: '工业', value: 30 },
  { source: '天然气', target: '居民', value: 25 },
  { source: '发电', target: '工业', value: 35 },
  { source: '发电', target: '居民', value: 10 }
];

网站用户行为路径

const userPathNodes = [
  { name: '首页' },
  { name: '产品页' },
  { name: '详情页' },
  { name: '购物车' },
  { name: '支付页' },
  { name: '订单完成' },
  { name: '离开' }
];

const userPathLinks = [
  { source: '首页', target: '产品页', value: 1000 },
  { source: '产品页', target: '详情页', value: 600 },
  { source: '详情页', target: '购物车', value: 300 },
  { source: '购物车', target: '支付页', value: 200 },
  { source: '支付页', target: '订单完成', value: 180 },
  { source: '首页', target: '离开', value: 400 },
  { source: '产品页', target: '离开', value: 300 }
];

高级技巧

自定义节点形状

series: [{
  type: 'sankey',
  nodeShape: 'roundRect',
  nodeStyle: {
    radius: 5
  },
  label: {
    formatter: function(params) {
      return `${params.name}\n${params.value}吨`;
    }
  }
}]

混合其他图表类型

series: [
  {
    type: 'sankey',
    // 桑基图配置
  },
  {
    type: 'pie',
    center: ['80%', '30%'],
    radius: '30%',
    data: [
      { value: 45, name: '煤炭' },
      { value: 30, name: '石油' },
      { value: 25, name: '天然气' }
    ]
  }
]

响应式设计

确保桑基图在不同设备上正常显示:

window.addEventListener('resize', function() {
  myChart.resize();
});

// 响应式配置
option = {
  responsive: true,
  media: [
    {
      query: { maxWidth: 768 },
      option: {
        series: [{
          label: { fontSize: 10 },
          nodeWidth: 10
        }]
      }
    }
  ]
}

数据预处理

对于原始数据通常需要预处理:

function processSankeyData(rawData) {
  const nodes = [];
  const nodeMap = new Map();
  const links = [];
  
  // 提取唯一节点
  rawData.forEach(item => {
    if (!nodeMap.has(item.source)) {
      nodeMap.set(item.source, true);
      nodes.push({ name: item.source });
    }
    if (!nodeMap.has(item.target)) {
      nodeMap.set(item.target, true);
      nodes.push({ name: item.target });
    }
  });
  
  // 聚合相同source-target的value
  const linkMap = new Map();
  rawData.forEach(item => {
    const key = `${item.source}|${item.target}`;
    if (linkMap.has(key)) {
      linkMap.get(key).value += item.value;
    } else {
      linkMap.set(key, { ...item });
    }
  });
  
  links.push(...linkMap.values());
  
  return { nodes, links };
}

国际化支持

为桑基图添加多语言支持:

const i18n = {
  en: {
    title: 'Energy Flow',
    tooltip: 'Flow value: {c}'
  },
  zh: {
    title: '能源流动图',
    tooltip: '流量值: {c}'
  }
};

function setLanguage(lang) {
  myChart.setOption({
    title: { text: i18n[lang].title },
    tooltip: { formatter: i18n[lang].tooltip }
  });
}

性能监控

添加图表性能监控:

myChart.on('rendered', function() {
  const perfData = myChart.getModel().getPerformanceData();
  console.log('渲染耗时:', perfData.renderTime);
});

// 大数据量时显示加载提示
myChart.showLoading({
  text: '数据加载中...',
  color: '#c23531',
  textColor: '#000',
  maskColor: 'rgba(255, 255, 255, 0.8)'
});

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步