Canvas画笔颜色拾取与渐变填充的核心是:一用getImageData读取像素RGBA值实现吸管功能,二用createLinearGradient/createRadialGradient创建渐变并赋给fillStyle/strokeStyle;二者可独立或组合使用,如从渐变调色板点击取色。

Canvas 实现画笔颜色拾取与渐变填充,核心在于两件事:一是用 getImageData 读取像素颜色作为“吸管”,二是用 createLinearGradient 或 createRadialGradient 构建渐变并赋给 fillStyle 或 strokeStyle。两者不冲突,可独立使用,也能组合——比如从渐变调色板里点选一种颜色设为当前画笔色。
画笔颜色拾取:从 canvas 上“吸”任意位置的颜色
这不是点击弹窗选色,而是实时读取 canvas 当前绘制内容中某一点的 RGBA 值:
- 确保目标图像或调色板已完整绘制到 canvas 上(比如一张用户上传图、一个自绘色条、或 HSV 色盘)
- 监听
click或mousemove事件,通过e.offsetX / e.offsetY或getBoundingClientRect()算出鼠标相对于 canvas 左上角的坐标 - 调用
ctx.getImageData(x, y, 1, 1),返回一个Uint8ClampedArray,前四项即[r, g, b, a](范围 0–255) - 把这四个值转成你想要的格式:RGB 字符串
rgb(255,128,64)、HEX#ff8040(注意补零)、或直接用于后续绘图的ctx.fillStyle = `rgba(${r},${g},${b},${a/255})` - 若拾取源是外部图片,务必提前设置
<img crossOrigin="anonymous">,否则会因跨域被拒绝
渐变填充:用 Canvas API 绘制线性或径向过渡色
渐变不是“贴图”,而是动态计算每个像素颜色的着色器,性能好、缩放无损:
-
线性渐变:调用
ctx.createLinearGradient(x0, y0, x1, y1),参数是起点和终点坐标(如从左到右:0,0,canvas.width,0) -
径向渐变:用
ctx.createRadialGradient(x0,y0,r0,x1,y1,r1),定义两个同心圆(中心点 + 半径),颜色从内圆平滑过渡到外圆 - 创建后,用
addColorStop(offset, color)添加色标,offset是 0–1 的归一化位置(如0表示起点,0.5表示中点),color支持任何 CSS 颜色格式(#ff0000、rgb(255,0,0)、hsl(0,100%,50%)都行) - 最后将渐变对象赋给
ctx.fillStyle(填色)或ctx.strokeStyle(描边),再调用fill()或stroke()即可生效
拾取 + 渐变结合:做一个可交互的调色板
典型做法是先画一个渐变条(比如横向 HSL 色条),再让用户点击它来获取某一位置的颜色作为当前画笔色:
立即学习“前端免费学习笔记(深入)”;
- 用
createLinearGradient(0,0,300,0)创建横跨 300px 宽的渐变,加多个addColorStop覆盖全色相(如 0→红、0.33→绿、0.66→蓝、1→红) - 把该渐变赋给
fillStyle,再用fillRect(0,0,300,30)绘出一条色带 - 监听
click事件,取e.offsetX(限制在 0–300 内),算出归一化位置pos = Math.max(0, Math.min(1, e.offsetX / 300)) - 根据这个
pos值反推对应 HSL 或 RGB 值(或直接用getImageData读像素——更通用,无需预知色值逻辑) - 拿到颜色后,存为全局变量
currentBrushColor,之后所有绘图操作(如beginPath+lineTo+stroke)都用它
注意事项与避坑点
几个容易卡住的细节:
- canvas 坐标系以左上角为原点,x 向右、y 向下,别和 CSS 盒模型混淆
-
getImageData返回的是整数数组,RGBA 各占 1 字节;透明度a=0表示完全透明,a=255表示完全不透明 - 渐变对象本身不“属于” canvas,可复用:同一个渐变可多次赋给不同
fillStyle,也可在不同 canvas 间传递 - 移动端需同时监听
touchstart和touchmove,并用touches[0].clientX/Y替代offsetX/Y - 如果 canvas 有 CSS 缩放(如
width:100%; height:auto),务必用getBoundingClientRect()换算真实像素坐标,避免比例错乱



















