Canvas不解析CSS变量,需用getComputedStyle().getPropertyValue()读取并trim()后赋值;高频绘制应缓存变量避免强制布局;注意色域、缩放、深色模式及主题切换后重绘。

Canvas不认CSS变量,必须手动“翻译”
直接写 ctx.fillStyle = "var(--primary-color)" 会静默失败,Canvas 渲染为黑色或透明——这不是 bug,是 Canvas 2D 上下文根本不解析 CSS 语法。它只接受最终计算出的颜色字符串:"#3b82f6"、"rgb(59, 130, 246)"、"LightGreen"(注意大小写),其他一律忽略。
用 getComputedStyle 安全读取变量值
这是唯一可靠方式,但容易踩坑:
- 必须传入已挂载的元素,读全局变量用
document.documentElement;读组件级变量(如)就得传document.getElementById("chart")- 必须用
.getPropertyValue('--primary-color'),不是.style.--primary-color(语法错误),也不是.cssText(不包含变量值)- 返回值是字符串,但可能带前导/尾随空格或换行,务必加
.trim();否则 Safari 旧版直接忽略,ctx.fillStyle失效变黑- 变量未定义时返回空字符串
"",不是undefined,别用== null判断,建议兜底:const color = getComputedStyle(root).getPropertyValue('--primary').trim() || '#000'高频绘制时别反复调用
getComputedStyle在
requestAnimationFrame或动画循环里每帧都读,会触发强制同步布局,明显卡顿。正确做法是:- 主题初始化或
themechange事件中读一次,缓存为 JS 变量 - 后续所有绘图直接用缓存值,比如
ctx.fillStyle = primaryColor - 如果变量本身是
rgba(59, 130, 246, 0.8)这类格式,Canvas 原生支持,但确保 alpha 是小数(0.8),不是百分比(80%)
颜色一致 ≠ 视觉一致,还要防色域和缩放干扰
即使你读对了、赋对了,Canvas 里画出来的颜色仍可能“发灰”或“偏暗”,原因不在代码逻辑,而在底层:
- Canvas 不做色彩管理,忠实地把输入值映射到 sRGB 输出通道;若设计稿来自 P3 色域(如 macOS Display P3 屏),数值相同但感知不同
-
canvas.width/canvas.height和canvas.style.width/canvas.style.height不一致时,图形被拉伸,抗锯齿混入额外像素,间接改变边缘颜色感知 - 深色模式下系统自动提亮文字(Chrome 对
color-scheme: dark的补偿)不会影响 Canvas 内文本渲染,导致 DOM 文字与 Canvas 文字明暗不一致
真正麻烦的不是怎么读变量,而是主题切换后是否立刻清空重绘——很多人改了
--primary-color,却忘了调用ctx.clearRect()和重新执行绘图逻辑。 - 必须用
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











