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 缩放后,线条在页面上的视觉粗细也约为原来的两倍。
备注:内容仅供参考。
