canvas的width/height必须用html属性定义,因为它们直接决定绘图缓冲区分辨率;仅用css设置仅缩放显示尺寸,导致图像拉伸、坐标错乱、描边变粗。

width 和 height 必须用 HTML 属性写死,不能靠 CSS 控制 —— 否则绘图坐标系、像素密度、描边粗细全乱套。
为什么 canvas.width/height 必须是 HTML 属性,不是 style?
Canvas 是一块“像素缓冲区”,width 和 height 属性直接决定内部位图的分辨率(比如 width="400" height="300" 就是 400×300 像素的帧缓冲)。CSS 的 style="width:800px;height:600px" 只是拉伸显示层,不改缓冲区大小。
后果很直接:
-
fillRect(100, 100, 50, 50)实际画在第 100 行/列像素上,但被 CSS 拉伸后,视觉位置偏移、动画轨迹错乱 - 圆变椭、文字模糊、描边变粗(
lineWidth = 1还是 1 像素,但被放大渲染) - 鼠标事件坐标需手动反向缩放,否则
getBoundingClientRect()返回的 clientX/Y 无法直接映射到绘图坐标
正确初始化 canvas 元素并获取上下文的顺序
拿到 DOM 元素后,必须调用 getContext("2d") 才能绘图 —— canvas 自身不提供任何绘制能力。
关键点:
- ✅ 正确写法:
const canvas = document.getElementById("myCanvas"); const ctx = canvas.getContext("2d"); - ⚠️ 同一个
canvas元素只能获取一种上下文:选了"2d"就不能再取"webgl",反之亦然 - ⚠️ 脚本若放在
里,getElementById可能返回null;要么用window.onload,要么把<script></script>放在前 - ? 提示文本写在标签内部即可:
<canvas width="400" height="300">您的浏览器不支持 Canvas</canvas>
响应式场景下怎么安全调整 canvas 尺寸?
如果页面需要适配不同屏幕(比如全屏图表、移动端横竖屏切换),不能只靠 CSS 缩放,必须同步重设缓冲区并重绘。
可行做法:
- 监听
resize事件,读取容器尺寸,再赋值给canvas.width和canvas.height - 重设尺寸后,
ctx状态不会自动保留:所有样式(fillStyle、lineWidth等)、路径、变换矩阵都会重置,必须重新设置 - 重绘逻辑要封装成函数,每次 resize 后调用,不能只改尺寸就指望画面自动更新
- 避免高频触发:可用
throttle或requestAnimationFrame控制重绘节奏
最常被忽略的一点:canvas 不是声明式 UI,它没有脏检查、没有 diff、没有自动刷新。你改了数据,画面不会变;你动了 style,缓冲区没动,图形就失真。一切得靠你亲手清、画、缩、算。











