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

如何用JS/Canvas实现平滑无硬边的同心径向渐变模糊甜甜圈效果

问题原因

渲染出现硬边由两个问题直接导致:

  • 色标存在颜色跳变:三个色标的透明度虽然都是0.1,但颜色在0位置是黑色、0.5位置跳成灰色、1位置又跳回黑色,相邻色标之间的颜色值不连续,渲染时自然会出现清晰的分界
  • 渐变创建逻辑不对:如果你的径向渐变是从圆心半径0的位置开始创建,中心区域会被直接填充,没法自然做出中间空心、内外边缘都柔化的环形效果。
实现方案

无硬边的模糊甜甜圈效果完全可以实现,核心逻辑是用同心双圆生成径向渐变,全程保持填充色一致,仅通过透明度的连续变化实现内外柔边,不要在色标位置做颜色或透明度的突变。

可直接运行的代码示例

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');

// 甜甜圈参数,可按需调整
const cx = canvas.width / 2;
const cy = canvas.height / 2;
const innerRingRadius = 60; // 环形实体部分的内半径
const ringThickness = 30; // 环形实体部分的厚度
const edgeBlur = 20; // 边缘模糊的范围
const gradientInnerR = innerRingRadius - edgeBlur;
const gradientOuterR = innerRingRadius + ringThickness + edgeBlur;

// 创建同心径向渐变
const gradient = ctx.createRadialGradient(
  cx, cy, gradientInnerR,
  cx, cy, gradientOuterR
);

// 配置色标:全程使用同一个灰色,仅调整透明度实现平滑过渡
const stopInnerSolid = edgeBlur / (gradientOuterR - gradientInnerR);
const stopOuterSolid = (gradientOuterR - edgeBlur - gradientInnerR) / (gradientOuterR - gradientInnerR);
gradient.addColorStop(0, "rgba(128, 128, 128, 0)");
gradient.addColorStop(stopInnerSolid, "rgba(128, 128, 128, 0.1)");
gradient.addColorStop(stopOuterSolid, "rgba(128, 128, 128, 0.1)");
gradient.addColorStop(1, "rgba(128, 128, 128, 0)");

// 填充圆形即可得到柔边甜甜圈
ctx.beginPath();
ctx.arc(cx, cy, gradientOuterR, 0, Math.PI * 2);
ctx.fillStyle = gradient;
ctx.fill();

// 想要更接近高斯模糊的柔化效果,可以额外加模糊滤镜,数值按需调整
// ctx.filter = 'blur(4px)';

关键注意点

  • 不要在不同色标上切换颜色:之前代码里黑、灰、黑的跳变是硬边的直接来源,做柔边环形时全程使用同一个目标色,只改透明度就行
  • 渐变内圆不要从半径0开始:把内圆半径设到内边缘模糊的起始位置,就能自然生成中心空心的效果,不需要额外擦除中心区域
  • 透明度过渡不能有断点:从完全透明到目标透明度、再回到完全透明的过程要连续,不要在色标位置突然跳变透明度或颜色
  • 如果需要更朦胧的效果,打开代码里注释的filter模糊属性即可,模糊半径越大边缘越柔和。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 20:51:20