如何使用HTML canvas实现渐变色的填充效果?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1009个文字,预计阅读时间需要5分钟。
在 `fillStyle` 属性中,必须设置为 `createLinearGradient()` 或 `createRadialGradient()` 返回的对象,字符串色值、数组色值、或由逗号分隔的色值。例如:
createLinearGradient() 的坐标不是百分比,是绝对像素点
四个参数 (x0, y0, x1, y1) 是画布坐标系中的点,不是宽高比例,也不是 CSS 百分比。写成 createLinearGradient("0%", "0%", "100%", "0") 会直接报错;写成 createLinearGradient(0, 0, canvas.width, 0) 才是从左到右铺满画布宽度的水平渐变。
常见错误:
- 起点终点重合(
x0 === x1 && y0 === y1),导致渐变退化为单色 - 误用
canvas.clientWidth或缩放后尺寸,而没用canvas.width/canvas.height(后者才是绘图坐标系基准) - 在
transform缩放后仍按原始坐标算轴线,结果方向偏移
addColorStop() 的 offset 必须是 0–1 的数字,不能是字符串
offset 参数只接受 number 类型,范围严格在 [0, 1] 内。传字符串如 "0.5" 或 "50%" 会被转成 0,所有颜色都堆在起点;传 1.2 或 -0.1 则被忽略或截断。
立即学习“前端免费学习笔记(深入)”;
合法写法:
grad.addColorStop(0, "red")grad.addColorStop(0.75, "rgba(0,100,255,0.8)")
危险写法:
-
grad.addColorStop("0.5", "blue")→ 静默失败 -
grad.addColorStop(0, "black"); grad.addColorStop(0, "white")→ 后者覆盖前者,只剩一个 stop
fillStyle 赋值后不会自动重置,多个图形共用同一渐变对象
fillStyle 是绘图上下文的状态属性,一旦设为某个渐变对象,后续所有 fillRect()、fill() 都沿用它,直到你显式改写。
典型坑:
- 循环中反复调用
createLinearGradient()但没重新赋给fillStyle,结果所有图形都用第一个渐变 - 以为
fillRect()会“清空”渐变状态,其实完全不会 - 想让每个矩形有独立渐变方向,必须在每次绘制前新建渐变并重新赋值
fillStyle
示例:两个不同方向的矩形
ctx.fillStyle = ctx.createLinearGradient(0, 0, 200, 0); ctx.fillRect(10, 10, 100, 50); <p>ctx.fillStyle = ctx.createLinearGradient(0, 0, 0, 100); // 新渐变 ctx.fillRect(10, 70, 100, 50);
径向渐变中 r0 和 r1 别设反,中心点发白常因 r0 === 0 且没配 colorStop(0)
createRadialGradient(x0,y0,r0,x1,y1,r1) 中,r0 是起始圆半径,r1 是结束圆半径。必须满足 r1 > r0,否则无渐变效果;若 r0 === 0 但没调用 addColorStop(0, ...),浏览器默认用第一个非零 stop 的颜色填充圆心,容易突兀发白或色块断裂。
移动端尤其注意:r1 超过画布尺寸 1.5 倍(如 >2000px)可能被渲染器降级处理,建议控制范围。
安全写法:
-
grad.addColorStop(0, "#000")—— 明确定义圆心色 -
grad.addColorStop(1, "#fff")—— 明确定义边缘色 -
r0 = 0,r1 = Math.max(canvas.width, canvas.height) * 0.8
渐变生效的前提极简:创建对象 → 至少两个 addColorStop() → 赋给 fillStyle → 调用 fillRect() 或 fill()。漏掉任一环,或者参数类型/范围不对,就只会看到黑色。最易被忽略的是 offset 的类型和 r1 > r0 这个硬约束。
本文共计1009个文字,预计阅读时间需要5分钟。
在 `fillStyle` 属性中,必须设置为 `createLinearGradient()` 或 `createRadialGradient()` 返回的对象,字符串色值、数组色值、或由逗号分隔的色值。例如:
createLinearGradient() 的坐标不是百分比,是绝对像素点
四个参数 (x0, y0, x1, y1) 是画布坐标系中的点,不是宽高比例,也不是 CSS 百分比。写成 createLinearGradient("0%", "0%", "100%", "0") 会直接报错;写成 createLinearGradient(0, 0, canvas.width, 0) 才是从左到右铺满画布宽度的水平渐变。
常见错误:
- 起点终点重合(
x0 === x1 && y0 === y1),导致渐变退化为单色 - 误用
canvas.clientWidth或缩放后尺寸,而没用canvas.width/canvas.height(后者才是绘图坐标系基准) - 在
transform缩放后仍按原始坐标算轴线,结果方向偏移
addColorStop() 的 offset 必须是 0–1 的数字,不能是字符串
offset 参数只接受 number 类型,范围严格在 [0, 1] 内。传字符串如 "0.5" 或 "50%" 会被转成 0,所有颜色都堆在起点;传 1.2 或 -0.1 则被忽略或截断。
立即学习“前端免费学习笔记(深入)”;
合法写法:
grad.addColorStop(0, "red")grad.addColorStop(0.75, "rgba(0,100,255,0.8)")
危险写法:
-
grad.addColorStop("0.5", "blue")→ 静默失败 -
grad.addColorStop(0, "black"); grad.addColorStop(0, "white")→ 后者覆盖前者,只剩一个 stop
fillStyle 赋值后不会自动重置,多个图形共用同一渐变对象
fillStyle 是绘图上下文的状态属性,一旦设为某个渐变对象,后续所有 fillRect()、fill() 都沿用它,直到你显式改写。
典型坑:
- 循环中反复调用
createLinearGradient()但没重新赋给fillStyle,结果所有图形都用第一个渐变 - 以为
fillRect()会“清空”渐变状态,其实完全不会 - 想让每个矩形有独立渐变方向,必须在每次绘制前新建渐变并重新赋值
fillStyle
示例:两个不同方向的矩形
ctx.fillStyle = ctx.createLinearGradient(0, 0, 200, 0); ctx.fillRect(10, 10, 100, 50); <p>ctx.fillStyle = ctx.createLinearGradient(0, 0, 0, 100); // 新渐变 ctx.fillRect(10, 70, 100, 50);
径向渐变中 r0 和 r1 别设反,中心点发白常因 r0 === 0 且没配 colorStop(0)
createRadialGradient(x0,y0,r0,x1,y1,r1) 中,r0 是起始圆半径,r1 是结束圆半径。必须满足 r1 > r0,否则无渐变效果;若 r0 === 0 但没调用 addColorStop(0, ...),浏览器默认用第一个非零 stop 的颜色填充圆心,容易突兀发白或色块断裂。
移动端尤其注意:r1 超过画布尺寸 1.5 倍(如 >2000px)可能被渲染器降级处理,建议控制范围。
安全写法:
-
grad.addColorStop(0, "#000")—— 明确定义圆心色 -
grad.addColorStop(1, "#fff")—— 明确定义边缘色 -
r0 = 0,r1 = Math.max(canvas.width, canvas.height) * 0.8
渐变生效的前提极简:创建对象 → 至少两个 addColorStop() → 赋给 fillStyle → 调用 fillRect() 或 fill()。漏掉任一环,或者参数类型/范围不对,就只会看到黑色。最易被忽略的是 offset 的类型和 r1 > r0 这个硬约束。

