createRadialGradient参数顺序为(x0,y0,r0,x1,y1,r1),前三个是起始圆圆心坐标与半径,后三个是结束圆圆心坐标与半径,坐标系以canvas左上角为原点,不感知CSS变换。

createRadialGradient 的参数顺序和坐标系容易搞反
这个函数返回一个 CanvasGradient 对象,但它的六个参数不是“起点圆 + 终点圆”的直觉顺序,而是:createRadialGradient(x0, y0, r0, x1, y1, r1) —— 前三个是**起始圆**(中心点 + 半径),后三个是**结束圆**(中心点 + 半径)。很多人误以为 r0 是外圆半径、r1 是内圆半径,其实只要 r1 > r0,渐变就从内向外扩散;如果 r0 > r1,浏览器仍会渲染,但视觉上可能意外收缩或出现空心环效果。
注意:所有坐标都基于 canvas 元素自身的左上角为原点(0, 0),不是 CSS 布局位置,也不是父容器坐标。若 canvas 被缩放或 transform 过,需手动换算,createRadialGradient 不感知 CSS 变换。
-
x0,y0是起始圆圆心(比如想从按钮中心开始渐变,就得用canvas.width / 2) -
r0通常设为0,让颜色从一个点平滑发散;设为较大值会产生“空心球”感 -
x1,y1和r1决定渐变影响范围的边界 —— 渐变色只在两圆之间的环形区域插值,超出r1的区域取最后一个addColorStop的颜色
addColorStop 的 offset 必须在 [0, 1] 区间且单调递增
给 radial gradient 添加颜色断点时,addColorStop(offset, color) 的 offset 不是像素值,而是归一化距离:0 表示起始圆边缘(r0 处),1 表示结束圆边缘(r1 处)。哪怕你把 r1 设成 200px,offset: 0.5 仍代表从 r0 到 r1 的中点位置(即半径为 r0 + 0.5 * (r1 - r0) 的圆上)。
- 如果传入
offset = 1.2,会抛出IndexSizeError - 如果先加
addColorStop(0.8, 'red')再加addColorStop(0.3, 'blue'),部分浏览器(如旧版 Safari)可能静默失败或渲染异常 - 常用组合:
addColorStop(0, '#fff')+addColorStop(1, '#333')做基础明暗过渡;想突出中心光斑,可加addColorStop(0.1, '#ffeb3b')
fillStyle 设置后必须立刻 fill,否则可能被后续绘图覆盖
Canvas 是状态机模型。ctx.fillStyle = gradient 只是设置当前填充样式,不触发任何绘制。真正生效要靠 ctx.fill() 或 ctx.fillRect() 等操作。常见错误是设置了 gradient,却忘了调用 fill,或者在 fill 前又调用了 ctx.beginPath() 但没重绘路径,导致空白。
立即学习“前端免费学习笔记(深入)”;
另外,gradient 对象绑定的是创建时的 canvas 尺寸。如果之后 canvas 的 width 或 height 属性被 JS 修改(比如 canvas.width = 500),已创建的 gradient 不会自动更新,必须重新调用 createRadialGradient。
- 动态调整 canvas 大小时,gradient 需重建 —— 没有“刷新”方法
- 不要复用同一个 gradient 对象去 fill 多个不同尺寸/位置的图形,除非你确认两者的相对坐标关系一致
- 调试时可用
ctx.strokeStyle = 'red'; ctx.stroke();先描边,确认路径是否正确闭合
性能敏感场景下避免高频重建 gradient
每次调用 createRadialGradient 都涉及内部对象分配和 GPU 资源准备。在动画循环(如 requestAnimationFrame)里反复新建 gradient,尤其配合大 canvas(>1000×1000),会明显掉帧。
- 静态背景渐变?提前创建一次,缓存 gradient 变量,重复赋值给
fillStyle - 需要随鼠标移动的高亮效果?可限制重建频率(如 throttle 到 60fps 以内),或改用
createLinearGradient+ 旋转模拟(更轻量) - Chrome DevTools 的 Rendering 面板勾选 “Paint flashing”,能直观看到 gradient 重建是否引发频繁重绘
最常被忽略的一点:gradient 的圆心坐标是绝对像素值,不是百分比。想实现响应式径向渐变,必须监听 resize 并手动重算 x0, y0, r1,不能指望 CSS width: 100% 自动适配 canvas 内部坐标系。



















