fillRect()的y值总不对,因Canvas原点在左上角、y增大向下,而柱状图需从底部向上生长;正确做法是先定基线baseY=canvas.height-paddingBottom,再用y=baseY-barHeight计算左上角纵坐标。

直接用 fillRect() 就能画出柱子,但关键在坐标换算和留白控制——不处理好 y 坐标和边距,柱子会贴顶、压字、错位甚至倒着长。
为什么 fillRect() 的 y 值总算不对
Canvas 的原点在左上角,y 越大越往下。而柱状图习惯“从底部往上长”,所以不能直接用 data[i] 当高度塞进 y 参数。
-
fillRect(x, y, width, height)的y是矩形**左上角**纵坐标,不是底边 - 正确做法:先确定基线位置(比如
canvas.height - paddingBottom),再用baseY - barHeight得到左上角y - 常见错误是写成
y = baseY + barHeight或直接y = barHeight,结果柱子飘在画布上方或被截断
barWidth 和 gap 怎么设才不重叠也不浪费空间
宽度和间距不是拍脑袋定的,得根据数据长度、画布宽度和左右留白反推。
- 先固定左右边距(如
marginLeft = 60,marginRight = 20)和柱间间隙(如gap = 20) - 可用宽度 =
canvas.width - marginLeft - marginRight - 单柱最大可用宽 =
(可用宽度 - gap * (data.length - 1)) / data.length,再向下取整防溢出 - 如果数据动态增减,建议用
Math.min(40, 计算值)设上限,避免柱子过窄难点击
刻度、文字、网格线容易糊成一团怎么办
所有辅助元素必须和柱子共用同一套坐标映射逻辑,否则对不齐。
立即学习“前端免费学习笔记(深入)”;
- Y 轴刻度值要按比例缩放:真实值
v→ 像素位置y = baseY - v * scaleFactor,其中scaleFactor = (可用高度) / Math.max(...data) - 文字用
ctx.textAlign = 'center'+ctx.textBaseline = 'bottom'对齐柱顶,否则标签悬空或压柱 - 画网格线前调
ctx.beginPath(),每条线用独立moveTo()/lineTo(),别连成折线 - 避免在循环里反复设置
ctx.font或ctx.fillStyle,提出来统一设
最易被忽略的是坐标系反转后,所有依赖 y 的操作(包括 isPointInPath() 检测、tooltip 定位、动画起始点)都得同步适配——漏掉一处,交互就失灵。



















