如何在HTML5 Canvas 2D上下文实现椭圆渐变描边?
实现Canvas 2D椭圆渐变描边的方法
直接对画布上下文应用缩放变换会同时拉伸/压缩描边宽度,导致描边粗细不均——这就是你遇到问题的根源。要实现均匀宽度的椭圆渐变描边,可以通过以下两种方法解决:
方法1:直接变换渐变对象(推荐)
Canvas的径向渐变对象支持setTransform()方法,可独立修改渐变的坐标空间,不会影响描边宽度。通过该方法将圆形渐变挤压为椭圆,同时保持描边的均匀宽度。
示例代码:
var cnv = document.createElement("canvas"), ctx = cnv.getContext("2d"); document.body.appendChild(cnv); ctx.lineWidth = 10; ctx.rect(20, 20, 100, 100); // 创建圆形径向渐变 var radialGrad = ctx.createRadialGradient(70, 70, 0, 70, 70, 100); radialGrad.addColorStop(0.4, "blue"); radialGrad.addColorStop(0.7, "red"); // 对渐变应用X轴缩放变换,保持渐变中心位置不变 // 变换矩阵参数:scaleX, skewX, skewY, scaleY, translateX, translateY radialGrad.setTransform(0.5, 0, 0, 1, 70 * (1 - 0.5), 0); ctx.strokeStyle = radialGrad; ctx.stroke();
原理说明:
setTransform()仅修改渐变的形状,不会影响画布上下文的其他绘制属性(如lineWidth),因此描边宽度保持均匀。- 矩阵中的
translateX参数用于补偿缩放带来的偏移,确保渐变中心仍对准矩形中心(70,70)。
方法2:离屏Canvas绘制渐变+裁剪(兼容旧浏览器)
如果需要兼容不支持渐变setTransform()的旧浏览器,可以用离屏Canvas绘制椭圆渐变,再通过裁剪和合成模式提取描边区域:
示例代码:
var cnv = document.createElement("canvas"), ctx = cnv.getContext("2d"); document.body.appendChild(cnv); // 先定义目标矩形路径 ctx.rect(20, 20, 100, 100); ctx.save(); // 创建离屏Canvas绘制椭圆渐变 var offscreenCanvas = document.createElement("canvas"); offscreenCanvas.width = cnv.width; offscreenCanvas.height = cnv.height; var offCtx = offscreenCanvas.getContext("2d"); // 在离屏Canvas上变换上下文绘制椭圆渐变 offCtx.translate(70, 70); offCtx.scale(0.5, 1); offCtx.translate(-70, -70); var radialGrad = offCtx.createRadialGradient(70, 70, 0, 70, 70, 100); radialGrad.addColorStop(0.4, "blue"); radialGrad.addColorStop(0.7, "red"); offCtx.fillStyle = radialGrad; offCtx.fillRect(0, 0, offscreenCanvas.width, offscreenCanvas.height); // 回到原Canvas,裁剪出描边区域并绘制渐变 ctx.clip(); ctx.globalCompositeOperation = "source-in"; ctx.drawImage(offscreenCanvas, 0, 0); ctx.restore();
原理说明:
- 离屏Canvas用于生成椭圆渐变背景,不影响原画布的描边宽度。
- 通过
clip()和source-in合成模式,只保留矩形描边区域内的渐变内容。
内容的提问来源于stack exchange,提问作者Ivan Kuckir
相关产品推荐
相关产品推荐

