You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

createLinearGradient方向异常:切线渐变曲线实现问题排查

问题根源

你踩的核心坑是:Canvas的线性渐变坐标是全局画布坐标,不是填充图形的局部坐标。你以为渐变会顺着四边形的上下中点连线方向填,但实际上createLinearGradient是在整个画布上生成一条渐变线,填充图形时只是截取这条线上对应位置的颜色,不会自动适配图形的方向。

解决办法:用坐标变换适配图形方向

要让渐变沿着你预期的切线方向(黑色线条)填充,得先把画布坐标系临时“切换”到四边形的局部方向上,创建渐变后再恢复原状态。具体步骤:

  1. 算出四边形上下边的中点midTop和midBottom
  2. 计算两点连线的方向角度和长度
  3. 保存当前画布状态,将坐标系平移到midTop,旋转到渐变方向
  4. 此时原切线方向变成了画布的垂直方向,直接创建从上到下的渐变即可
  5. 填充图形后恢复原坐标系
修改后的代码示例
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.lineTo(x3, y3);
ctx.lineTo(x4, y4);
ctx.closePath(); // 别忘了闭合路径,否则填充可能出现缺口

const midTop = { x: (x1 + x2) / 2, y: (y1 + y2) / 2 };
const midBottom = { x: (x3 + x4) / 2, y: (y3 + y4) / 2 };

// 计算渐变方向的角度和长度
const dx = midBottom.x - midTop.x;
const dy = midBottom.y - midTop.y;
const angle = Math.atan2(dy, dx);
const gradientLength = Math.sqrt(dx*dx + dy*dy);

ctx.save();
// 平移到顶部中点,旋转到渐变方向
ctx.translate(midTop.x, midTop.y);
ctx.rotate(angle);

// 此时垂直方向对应原切线方向,创建渐变
const gradient = ctx.createLinearGradient(0, 0, 0, gradientLength);
gradient.addColorStop(0, "#3acbfcc3");
gradient.addColorStop(1, "#ffffff00");

ctx.fillStyle = gradient;
ctx.fill();

ctx.restore(); // 恢复原坐标系
额外提醒
  • 要是不想用变换,也可以计算一条足够长的全局渐变线,确保四边形顶部完全落在蓝色色标区域、底部完全落在透明色标区域,但这种方法需要计算渐变线的延长线,不如变换直观可靠。
  • 必须调用ctx.closePath(),否则图形边缘可能出现漏色,影响渐变显示效果。

内容的提问来源于stack exchange,提问作者Lol Lol

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 18:32:47