PAYATHON 2026

Canvas lineWidth 大于 1 时如何让多边形保持在边界内?

数据小许

结论

Canvas 的 lineWidth 会以路径为中心向两侧绘制,不会改变 moveTo() 或 lineTo() 的顶点坐标,但描边可能超出顶点围成的几何边界。若要将最终像素限制在指定矩形内,可以先用 ctx.rect() 和 ctx.clip() 创建裁剪区域,再绘制多边形。

示例中,路径坐标范围为 x = 100…112、y = 100…124。线宽为 5 时,描边通常会从路径向两侧各延伸约 2.5 个 Canvas 单位。顶点连接处也可能因默认的 lineJoin 产生尖角。

用裁剪区域限制绘制范围

将边界矩形传给绘制函数,并在描边前设置裁剪区域:

function drawPolygon(ctx, points, color, lineWidth, bounds) {
  ctx.save();

  ctx.beginPath();
  ctx.rect(bounds.x, bounds.y, bounds.width, bounds.height);
  ctx.clip();

  ctx.strokeStyle = color;
  ctx.lineWidth = lineWidth;
  ctx.beginPath();
  ctx.moveTo(points[0], points[1]);
  for (let i = 2; i < points.length; i += 2) {
    ctx.lineTo(points[i], points[i + 1]);
  }
  ctx.stroke();

  ctx.restore();
}

const line = [112, 112, 100, 100, 112, 124, 112, 112];
drawPolygon(ctx, line, 'red', 5, {
  x: 100,
  y: 100,
  width: 12,
  height: 26
});

clip() 会限制后续绘制操作。save() 和 restore() 可将裁剪区域的影响限定在这次绘制中。裁剪可能会切掉边界处的描边,这是让绘制结果保持在矩形内的直接方法。

减少尖角

Canvas 默认用 miter 连接线段。夹角较小时,连接处可能形成超出常规线宽范围的尖角。可以改用 bevel 或 round:

ctx.lineJoin = 'bevel'; // 或 'round'

这会改变角的外观,但描边仍可能超出路径边界。要严格限制绘制范围,仍需使用裁剪,或自行计算向内偏移后的路径。

关于 CSS 缩放

style="transform: scale(2);" 会将 Canvas 的显示尺寸放大两倍,描边也会随之缩放,但路径在 Canvas 坐标系中的几何关系不变。lineWidth 使用 Canvas 坐标单位,因此经过这种 CSS 缩放后,线条在页面上的视觉粗细也约为原来的两倍。

备注:内容仅供参考。