必须同时设置 canvas 的 HTML width/height 属性和 CSS style,因为前者决定像素缓冲区尺寸(位图分辨率),后者仅控制显示框大小;混用或只用 CSS 会导致模糊、坐标偏移、形状失真等问题。

不能用 CSS 代替 width 和 height 属性,因为二者控制的是完全不同的东西:HTML 属性决定画布的**像素缓冲区尺寸**,CSS 只控制 DOM 元素的**显示框大小**。混用或只用 CSS,图形就糊、坐标就偏、圆就变椭圆——这不是渲染 bug,是底层机制使然。
canvas.width/height 是位图分辨率,不是样式
width 和 height 是 <canvas> 的 HTML 属性,浏览器靠它分配一块固定像素数的内存区域(比如 800×600),所有绘图操作(lineWidth、文字、getImageData())都基于这个像素网格。它不是“看起来多大”,而是“能画多精细”。
- 不设时默认为
300×150,不是“没写”,是硬编码值 - 写成
width="800px"或width=800.5会被忽略,回退到默认值 -
canvas.width = 800会清空画布并重置上下文状态(包括变换矩阵、裁剪路径等),这是预期行为
只用 CSS 设置 width/height 必然拉伸模糊
写 style="width: 800px; height: 600px" 而不设 HTML 属性,等于把一张 300×150 的位图强行撑满显示区域——浏览器只能插值缩放,结果就是:
-
ctx.lineWidth = 1实际渲染出 2–3 像素宽的线(取决于缩放比) - 圆形边缘发虚,
isPointInPath()判断失效 - 鼠标点击坐标映射错位,
clientX/clientY需手动换算才能对齐 - 高 DPI 设备(
window.devicePixelRatio > 1)下锯齿更明显,比如devicePixelRatio === 2时,style="width:400px"实际只用了 200 物理像素去填
响应式场景下必须同步更新 HTML 属性和 devicePixelRatio
监听 window.resize 不够,关键是要根据真实布局尺寸和设备像素比重设缓冲区:
立即学习“前端免费学习笔记(深入)”;
- 先读取显示尺寸:
const w = canvas.clientWidth; const h = canvas.clientHeight; - 再设缓冲区:
canvas.width = w * window.devicePixelRatio; canvas.height = h * window.devicePixelRatio; - 最后缩放显示层:
canvas.style.width = w + "px"; canvas.style.height = h + "px"; - 别忘了重绘内容——
canvas.width赋值会清空画布 - 如果后续某处 CSS 覆盖了
canvas的显示尺寸,但没同步更新其width/height,失真就静默存在,直到你画斜线、贴图或做精确交互才暴露
真正容易被忽略的,不是初始化没设对,而是动态变化时只改了 style 却忘了重设 width/height,尤其在移动端 viewport 缩放、横竖屏切换、或第三方 UI 框架注入样式后——失真不会报错,只会悄悄腐蚀精度。



















