createLinearGradient(x0,y0,x1,y1)参数按起点x、y和终点x、y顺序定义渐变轴线,坐标系以canvas左上角为原点;addColorStop的offset必须为0–1间的归一化值,非像素单位。

createLinearGradient 的参数顺序和坐标系怎么理解
canvas 的 createLinearGradient 接收 4 个参数:x0, y0, x1, y1,代表渐变起点和终点的坐标。关键点在于:这些坐标是相对于当前 canvas 坐标系(左上角为原点),不是相对于绘制图形本身。比如你画一个矩形在 (100, 50),但传给 createLinearGradient 的 (0, 0, 0, 100) 仍是从 canvas 左上角开始算起——不是从矩形左上角。
常见错误是误以为参数以图形为基准,结果渐变“飘走”或完全不可见。建议先用 strokeRect(0, 0, 200, 200) 搭建参考框,再叠加渐变填充观察效果。
-
(0, 0, 100, 0)→ 水平从左到右渐变 -
(0, 0, 0, 100)→ 垂直从上到下渐变 -
(0, 0, 100, 100)→ 对角线渐变(左上→右下)
addColorStop 的 offset 值必须在 0–1 范围内
addColorStop 的第一个参数是 offset,它表示颜色在渐变轴上的相对位置,0 是起点,1 是终点。超出范围(如 -0.1 或 1.5)会直接报错:IndexSizeError: The index is not in the allowed range.
注意:这个 offset 不是像素值,也不受 canvas 缩放、transform 影响;它只和你定义的那条渐变线段(x0,y0 → x1,y1)有关。即使你画的图形很小,只要渐变线足够长,颜色依然按比例分布。
立即学习“前端免费学习笔记(深入)”;
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 两个色停点就用
0和1最稳妥 - 想强调中间色,可以加
0.5,但别写成50或0.5px - 重复添加相同 offset 不会覆盖,而是按调用顺序叠加(但浏览器通常只取最后一个)
fillStyle 必须在 beginPath 之后、fill/stroke 之前赋值
渐变对象要通过赋值给 fillStyle 才生效,但时机很关键:必须在调用 fill() 或 stroke() 之前设置,且最好在 beginPath() 之后。如果提前设了 fillStyle,又执行了其他路径操作(比如 arc() 后跟 rect()),而没重设 fillStyle,后一个图形仍会沿用之前的渐变——这不一定是 bug,但容易误判为“渐变没生效”。
典型错误写法:ctx.fillStyle = gradient; ctx.fillRect(0,0,100,100); ctx.beginPath(); ctx.arc(50,50,30,0,Math.PI*2); ctx.fill(); —— 圆也会被同个渐变填充,除非你中间重新赋值 fillStyle。
- 每次绘制新图形前,显式设置
fillStyle更安全 - 渐变对象可复用,但不要假设“设一次管全场”
- 调试时临时换成纯色(如
'red')能快速判断是渐变逻辑问题还是路径/绘制顺序问题
高 DPI 屏幕下渐变可能模糊?注意 canvas 的实际渲染尺寸
在 Retina 或 Windows 高缩放屏上,如果只设置 canvas 的 CSS 宽高(如 style="width:300px;height:150px"),但没设置 width 和 height 属性,canvas 会用默认 300×150 像素缓冲区渲染,再被拉伸,导致渐变边缘发虚甚至断层。
解决方法是显式设置 canvas 元素的 width 和 height 属性,并根据 window.devicePixelRatio 缩放:
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
const dpr = window.devicePixelRatio || 1;
canvas.width = 300 * dpr;
canvas.height = 150 * dpr;
canvas.style.width = '300px';
canvas.style.height = '150px';
ctx.scale(dpr, dpr);否则,哪怕 createLinearGradient 参数完全正确,渐变在视觉上也会失真——这不是渐变函数的问题,是像素对齐没做好。


















