如何创建两端宽度可变的桑基图?求适配JavaScript库
如何实现两端宽度不同的流量可视化图形?
我想要制作如下示例图所示的可视化图形:
原本我认为桑基图(Sankey diagram)符合需求,因此使用了chartjs-chart-sankey库,实现代码如下:
实现代码
JavaScript 代码
const ctx = document.getElementById('myChart'); const colors = { a: 'red', b: 'green', c: 'blue', d: 'gray' }; const getColor = (key) => colors[key]; const chart = new Chart(ctx, { type: 'sankey', data: { datasets: [{ label: 'My sankey', data: [{ from: 'a', to: 'b', flow: 10 }, { from: 'a', to: 'c', flow: 5 }, { from: 'b', to: 'c', flow: 10 }, { from: 'd', to: 'c', flow: 7 }], colorFrom: (c) => getColor(c.dataset.data[c.dataIndex].from), colorTo: (c) => getColor(c.dataset.data[c.dataIndex].to), colorMode: 'gradient', // or 'from' or 'to' /* optional labels */ labels: { a: 'Label A', b: 'Label B', c: 'Label C', d: 'Label D' }, priority: { b: 1, d: 0 }, column: { d: 1 }, size: 'max', }] }, });
HTML 代码
<main style="height: 200px; width: 400px;"> <canvas id="myChart" style="width: 300px;"></canvas> </main> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script src="https://cdn.jsdelivr.net/npm/chartjs-chart-sankey"></script>
但该库无法实现同一流(flow)起始端与结束端宽度不同的效果,每个流的两端宽度始终一致。我的实际需求是展示公司产品与营收数据:产品A占销量的10%(图左侧)、贡献40%的营收(图右侧),产品B占销量的30%、贡献10%的营收。请问该如何制作此类图形,应选用哪个库?
解决方案
首先明确:你需要的不是传统桑基图(传统桑基图严格遵循流量守恒,即每个流的两端宽度必须一致),而是一种不对称的双向条形连接图(也常被称为哑铃图的进阶版或非守恒流量图)。
推荐使用的库
D3.js
自由度极高,可以完全自定义绘制这类图形。核心思路是:- 在画布左右两侧分别绘制两组条形图,左侧对应销量占比,右侧对应营收占比;
- 为每个产品的左右条形,用贝塞尔曲线或平滑曲线连接对应的边缘,根据条形宽度调整曲线的起点和终点位置;
- 可自定义颜色、标签、动画等细节。
简单实现思路示例:
// 示例数据 const data = [ { name: "产品A", sales: 10, revenue: 40, color: "#ff4444" }, { name: "产品B", sales: 30, revenue: 10, color: "#00C851" } ]; // 计算布局:左侧条形位置、宽度,右侧条形位置、宽度 // 绘制左右矩形 // 绘制连接曲线Highcharts
可通过组合条形图和自定义SVG连线的方式实现,或利用其灵活的绘图API,手动绘制连接左右条形的曲线。Plotly.js
支持通过自定义trace实现此类图形,或使用其“parallel categories”组件的变种配置,也可结合条形图和形状(shape)绘制连线。
核心逻辑
这类图形的本质是两个独立的条形图+自定义连接曲线,不需要遵循桑基图的流量守恒规则,因此直接使用桑基图库无法满足需求,必须选择支持自定义绘图或非守恒流量可视化的工具。
内容的提问来源于stack exchange,提问作者dada17xs
相关产品推荐
相关产品推荐

