createLinearGradient方向异常:切线渐变曲线实现问题排查
问题根源
你踩的核心坑是:Canvas的线性渐变坐标是全局画布坐标,不是填充图形的局部坐标。你以为渐变会顺着四边形的上下中点连线方向填,但实际上createLinearGradient是在整个画布上生成一条渐变线,填充图形时只是截取这条线上对应位置的颜色,不会自动适配图形的方向。
解决办法:用坐标变换适配图形方向
要让渐变沿着你预期的切线方向(黑色线条)填充,得先把画布坐标系临时“切换”到四边形的局部方向上,创建渐变后再恢复原状态。具体步骤:
- 算出四边形上下边的中点
midTop和midBottom - 计算两点连线的方向角度和长度
- 保存当前画布状态,将坐标系平移到
midTop,旋转到渐变方向 - 此时原切线方向变成了画布的垂直方向,直接创建从上到下的渐变即可
- 填充图形后恢复原坐标系
修改后的代码示例
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
相关产品推荐
相关产品推荐

