canvas虚线不显示的主因是未在stroke前调用beginpath();setlinedash仅对下次stroke生效且需绑定当前路径,空数组[]表示实线,null会报错,高dpi需乘devicepixelratio校正。

Canvas setLineDash 画不出虚线?先检查 context 是否已开始路径
绝大多数“虚线不显示”问题,不是 setLineDash 写错了,而是调用它之前没执行 beginPath(),或者在 stroke() 之后又改了 dash 设置。Canvas 的虚线样式只对「下一次 stroke」生效,且必须绑定在当前路径上。
-
setLineDash必须在stroke()前调用,且最好紧挨着stroke()—— 中间插入moveTo或lineTo不影响,但插入beginPath()就会清空 dash 状态 - 如果画多条线想用不同虚线,每条都得单独
beginPath() → setLineDash() → stroke() - 在 Retina 屏或高 DPI 设备上,
[1, 1]这种极细虚线可能视觉上“消失”,建议最小用[2, 2]
setLineDash 参数是数组,但传空数组或 null 行为完全不同
setLineDash([]) 是实线(规范定义),而 setLineDash(null) 或 setLineDash(undefined) 在多数浏览器会抛错或静默失败——别依赖 null 清除虚线。
- 想恢复实线,明确写
ctx.setLineDash([]) - 数组长度为奇数(如
[5, 3, 2])也合法:Canvas 会自动复制一遍变成偶数长度([5, 3, 2, 5, 3, 2])再渲染 - 数值支持小数,比如
[1.5, 2.5],但低于 0.5 可能被像素对齐抹掉
Canvas 虚线不随缩放变化?那是没考虑 devicePixelRatio
用 canvas.width/canvas.height 设置画布尺寸时,若 CSS 样式放大了 canvas 元素(比如 width: 100%),虚线间距会被拉伸变形——因为 setLineDash 的单位是 CSS 像素,不是逻辑像素。
- 正确做法:获取
devicePixelRatio,把 dash 数组每个值乘上它,再传给setLineDash - 例如设备比为 2,想要视觉上 2px 空隙,就得传
[4, 4]而不是[2, 2] - 注意:只对通过 CSS 缩放的 canvas 有影响;用
transform: scale()则整个路径(含虚线)一起缩放,反而更可控
strokeRect 和 fillRect 不能直接用 setLineDash
strokeRect() 是原子操作,内部隐式调用了路径开始/结束,不会继承当前 setLineDash 设置。想给矩形加虚线边框,必须手动画路径。
立即学习“前端免费学习笔记(深入)”;
- 错:
ctx.setLineDash([4,4]); ctx.strokeRect(10,10,100,50);→ 实线 - 对:
ctx.beginPath(); ctx.rect(10,10,100,50); ctx.setLineDash([4,4]); ctx.stroke(); - 同理,
arc()、clearRect()等非路径函数都不响应 dash 设置
虚线最麻烦的从来不是怎么设参数,而是它和路径生命周期、设备像素、绘制方式这三者的耦合太紧——漏掉其中一环,看起来就像 API 失效了。











