最省事方案是用Chart.js配合chartjs-chart-waterfall插件,需版本匹配并显式注册;纯CSS仅适合静态演示,D3.js灵活但连接线易出错,关键在正确计算桥接线起点终点及差值标签位置。

用 Chart.js 画瀑布图最省事,但得装插件
原生 Chart.js 不支持瀑布图,直接写 type: 'waterfall' 会报错 Unknown chart type: waterfall。必须额外引入社区插件 chartjs-chart-waterfall,且版本要对齐:Chart.js v4.x 对应插件 v4.0.0+,v3 版本用不到 v4 的插件。
安装后需显式注册:
import { WaterfallController, WaterfallElement } from 'chartjs-chart-waterfall';
Chart.register(WaterfallController, WaterfallElement);
- 没调
Chart.register(),控制台不报错但图表空白 -
data.datasets[0].data里每个对象必须带value和label,可选color覆盖单柱颜色 - “总计”项要用
isTotal: true标记,否则不会加粗显示并自动累加
纯 CSS + HTML 能做静态瀑布图,但只适合演示场景
不用 JS 就想展示固定数据的瀑布效果,可以用带边框的 <div> 模拟柱子,靠 position: relative 和 top 偏移实现阶梯连接线。但所有数值、高度、间距都得手动算 px,比如总高 400px,某项占 30%,就得写 height: 120px。
- 数据一变就要重算所有
height和top,维护成本高 - 无法响应式:小屏下文字换行会撑乱布局,
vw单位也难对齐连接线 - 无障碍支持差:没有语义化标签,屏幕阅读器读不出数值和含义
D3.js 实现灵活但连接线逻辑容易写错
瀑布图关键不在柱子,而在柱与柱之间的“桥接线”——它得从上一柱顶部或底部出发,连到当前柱底部,并标注差值。用 D3.js 时,常见错误是直接用 d3.line() 连两个点,结果线段被裁出画布外,或起点/终点坐标算反(比如把“上一柱顶部”当成 y=0)。
立即学习“前端免费学习笔记(深入)”;
- 推荐先用
d3.stack()预计算每根柱的start和end值,再基于这些生成连接线路径 - 差值标签位置别硬写
transform="translate(10, -5)",应动态取两柱中点 x 和上柱 end y 做锚点 - 负值柱子的连接线方向会反转,必须单独判断
if (d.value 调整起始顺序
移动端适配时,柱宽和字体大小必须设为相对单位
瀑布图在手机上最常崩在两点:柱子挤成一条线,或数值标签重叠看不清。用 Chart.js 时,options.scales.x.ticks.maxRotation 设成 0 强制横排,配合 autoSkip: true;柱宽不能写死 barThickness: 24,得用 maxBarThickness: 24 让它自适应。
-
fontSize必须用rem或em,写12px在 iPhone 上会小到看不见 - 连接线上的差值标签如果超出容器,
clipPath容易切掉一半,不如直接设overflow: visible并加大外边距 - 真机调试时发现 iOS Safari 对
canvas抗锯齿处理更激进,细线容易发虚,可加ctx.imageSmoothingEnabled = false
瀑布图真正难的不是画出来,是让差值计算、连接逻辑、响应式缩放三者不互相打架。多数人卡在第二步——以为画出柱子就完了,其实连接线的坐标体系和数据映射才是分水岭。



















