用createLinearGradient()创建渐变对象并赋给fillStyle,再调用addColorStop()添加色标(offset为0–1小数),才能实现线性渐变;纯色或非法值会退为黑色。
canvas fillStyle 怎么用线性渐变替代纯色
直接用 canvasrenderingcontext2d.createlineargradient() 创建渐变对象,再赋给 fillstyle —— 这是唯一能触发颜色过渡的路径。纯色 fillstyle 不会过渡,哪怕你写 "#ff0000,#0000ff" 也没用,浏览器只当非法值处理成黑色。
常见错误是漏掉 .addColorStop() 调用,或者把位置参数写成百分比字符串(如 "50%"),实际必须是 0–1 的小数。
-
createLinearGradient(x0, y0, x1, y1)的四个参数是坐标,不是宽高比例;起点和终点重合会导致渐变失效(退化为单色) - 至少调用一次
.addColorStop(offset, color),offset必须在 [0, 1] 范围内,color支持所有 CSS 颜色格式("rgba(255,0,0,0.5)"也合法) - 渐变方向由 (x0,y0)→(x1,y1) 矢量决定,和 canvas 绘图区域大小无关;画布缩放或 transform 会影响最终视觉效果,但不改变渐变定义本身
径向渐变在 canvas 中怎么避免中间发白或色块断裂
createRadialGradient(x0, y0, r0, x1, y1, r1) 的六个参数里,r0 和 r1 是半径,不是直径;如果 r0 === 0 且没设中心色,浏览器默认用起始圆边缘色填充中心点,容易出现突兀白点。
真实场景中常因 r1 设得太小,导致渐变范围远小于绘制区域,看起来像一块糊状色斑。
- 确保
r1 > r0,否则渐变无意义;多数情况设r0 = 0是安全的,但必须配一个.addColorStop(0, ...) - 起始圆心 (x0,y0) 和结束圆心 (x1,y1) 可以不同,实现偏移光晕效果;但若两者距离过大,而
r1又小,会出现大面积未定义区域(渲染为透明黑) - 移动端 canvas 渲染器对超大
r1值(比如 >2000)可能降级处理,建议控制在画布尺寸 1.5 倍以内
fillRect 和 beginPath + fill 绘制渐变时行为不一样?
是的,而且区别关键在「状态继承」:fillStyle 是上下文状态的一部分,只要没被覆盖,后续所有 fill() 或 fillRect() 都沿用当前渐变对象——哪怕这个对象早已被变量释放。
立即学习“前端免费学习笔记(深入)”;
典型坑:循环中反复创建新渐变但没重新赋给 fillStyle,结果所有图形都用第一个渐变;或者误以为 fillRect() 会自动 reset 渐变,其实它完全不碰绘图状态。
-
fillRect()是独立绘制命令,不依赖路径,直接用当前fillStyle -
beginPath() → moveTo() → lineTo() → fill()这套流程里,fill()同样读取当前fillStyle,和fillRect()无本质区别 - 渐变对象本身没有“绑定”到某次绘制;只要
fillStyle指向它,就一直生效,直到你改写fillStyle或页面卸载
canvas 渐变性能差、动画卡顿怎么办
渐变对象创建本身开销不大,但频繁新建 + 赋值 fillStyle 在低端设备上会明显拖慢帧率,尤其每帧都重算坐标或颜色时。
更隐蔽的问题是:渐变对象不会被 GC 自动回收,如果在 requestAnimationFrame 里不断 new 出新渐变又不保留引用,Chrome 会堆积大量待回收对象,引发间歇性卡顿。
- 复用渐变对象:提前创建好,运行时只改
.addColorStop()或调整fillStyle,不要每帧 new - 避免在动画循环里调用
createLinearGradient();如果起点/终点需动态计算,先算好数值,再批量更新已有渐变的 stop 颜色 - 用
ctx.save()/ctx.restore()包裹渐变操作并不能提升性能,反而增加栈开销;真正有效的是减少渐变对象生成频次
渐变不是万能的过渡方案,复杂动画里有时用两层 canvas + opacity 淡入淡出,比实时计算 20 个渐变更稳。











