canvas线性渐变需调用addcolorstop至少两次(如0和1位置),起止点应超出绘制区域(如矩形宽100则设-50到150),且fillstyle必须在fill()前赋值,否则显示为透明黑或无效果。

canvas线性渐变怎么写才不会是纯色?
Canvas里createLinearGradient返回的渐变对象,必须手动调用addColorStop添加至少两个色标,否则fillStyle会退化为透明黑(不是默认白,也不是画布底色)。
- 只调一次
addColorStop(0, '#fff')→ 实际无渲染效果,矩形看起来是空的 - 起止点坐标要落在绘制区域外才有过渡感:比如画一个
100x100矩形,却设createLinearGradient(0,0,100,100),渐变会紧贴边缘;想让颜色从左外侧平滑进来,可设(-50,0,150,0) - 坐标系基于Canvas元素自身,不受
transform影响——缩放/旋转后仍按原始像素坐标算渐变方向
径向渐变圆心偏移后颜色突然断裂?
createRadialGradient的前三个参数是“内圆圆心x/y + 半径”,后三个是“外圆圆心x/y + 半径”。很多人误以为两组圆心必须重合,其实可以不同——但一旦偏移过大,外圆覆盖不到绘制区域,就会出现中间一块实色、周围透明的“黑洞”现象。
- 常见错误:
createRadialGradient(50,50,0, 50,50,200)是对的;但写成createRadialGradient(50,50,0, 200,200,200)时,外圆中心跑出画布,渐变失效 - 安全做法:先确保外圆半径足够大(比如取Canvas宽高对角线长度),再微调圆心位置
- 移动端注意:高DPR屏幕下,用
canvas.width/canvas.height而非canvas.clientWidth算坐标,否则渐变在Retina屏上严重错位
fillStyle设了渐变但图形没变色?
最常被忽略的是:渐变对象必须在fill()或stroke()**之前**赋给fillStyle,且不能复用已用于strokeStyle的同一对象(部分旧版safari会出错)。
- 错误顺序:
ctx.fillRect(); ctx.fillStyle = gradient;→ 无效 - 别把渐变存在闭包外反复赋值:每次重绘都该重新创建
createLinearGradient并加色标,缓存渐变对象在Canvas尺寸变化后会错位 - 用
ctx.save()/ctx.restore()包裹渐变设置,避免污染后续非渐变绘制 - 检查
fillStyle是否被其他逻辑覆盖(比如某个工具函数末尾硬写了ctx.fillStyle = '#000')
渐变性能差、动画卡顿怎么办?
每帧都调用createLinearGradient+addColorStop是CPU密集操作,尤其在60fps动画中明显掉帧。真正需要动态变化的只是色标颜色或位置,而非整个渐变结构。
立即学习“前端免费学习笔记(深入)”;
- 高频重绘场景:提前创建好渐变对象,只在循环中改
gradient.addColorStop()不行——这个方法不可逆;正确做法是用CanvasGradient对象配合ctx.fillStyle重新赋值,但色标必须重设 - 折中方案:用
createPattern配合小尺寸渐变PNG(仅适用于固定方向/比例的背景) - 更彻底的解法:CSS
background-image: linear-gradient叠加在Canvas上,Canvas只负责动态内容,渐变交给合成器处理
渐变坐标的像素级精度和色标插入时机,比想象中更敏感——少一次addColorStop、多一个save()遗漏,都可能让整块背景消失不见。