butt 端点详细讲解
一、什么是 butt 端点?
butt 是 Canvas 2D 上下文中 lineCap 属性的三个可选值之一,它指定了线条端点的样式。butt 表示线条的端点是平头,线条精确地在终点坐标处截止,没有任何延伸。
二、词源解析
| 单词 | 词源 | 含义 |
|---|---|---|
| butt | 古法语 but(目标、末端) | 平头、末端、抵住 |
这个词源很有意思:
在射箭中,
butt指靶子——箭射中目标时“抵住”靶心在线条中,
butt指线条正好在终点处“抵住”截止,没有多余部分
三、语法
ctx.lineCap = "butt"; // 平头端点(默认值)
四、三种端点样式对比
为了更好地理解 butt,需要对比另外两种端点:
| 值 | 名称 | 效果 | 示意图 |
|---|---|---|---|
butt | 平头 | 线条精确在终点截止 | ──────┼ |
round | 圆头 | 端点加一个半圆 | ──────● |
square | 方头 | 端点加一个矩形 | ──────■ |
视觉对比
实际路径:起点 (50,50) 到终点 (150,50) butt: 50 150 └──────────────┘ 正好在50和150处截止 round: 50 150 ●──────────────● 两端各多出半个圆(半径=线宽/2) square: 50 150 ■──────────────■ 两端各多出半个方形(长度=线宽/2)
五、代码示例
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.lineWidth = 20; // 设置粗线,更容易看清端点
// 画一条 butt 端点的线(蓝色)
ctx.beginPath();
ctx.strokeStyle = 'blue';
ctx.lineCap = 'butt';
ctx.moveTo(50, 50);
ctx.lineTo(250, 50);
ctx.stroke();
// 画一条 round 端点的线(红色)
ctx.beginPath();
ctx.strokeStyle = 'red';
ctx.lineCap = 'round';
ctx.moveTo(50, 100);
ctx.lineTo(250, 100);
ctx.stroke();
// 画一条 square 端点的线(绿色)
ctx.beginPath();
ctx.strokeStyle = 'green';
ctx.lineCap = 'square';
ctx.moveTo(50, 150);
ctx.lineTo(250, 150);
ctx.stroke();
// 标记实际起点和终点位置
ctx.fillStyle = 'black';
ctx.fillRect(48, 40, 4, 120); // 起点标记 x=50
ctx.fillRect(248, 40, 4, 120); // 终点标记 x=250执行结果
蓝色线(butt):正好在两个黑色标记之间,没有超出
红色线(round):两端超出黑色标记,呈半圆形
绿色线(square):两端超出黑色标记,呈方形
六、butt 的特点
优点
精确控制:线条长度完全符合指定的起点和终点
节省空间:不会有多余的延伸
默认值:不需要额外设置
缺点
在绘制非常粗的线条时,端点看起来可能有点“突然”
七、在五子棋代码中的应用
在五子棋代码中:
cav.strokeStyle = "rgb(147,109,70)"; cav.rect(115 + j * 30, 85 + i * 30, 30, 30); cav.stroke();
这里没有显式设置 lineCap,使用的是默认值 butt。对于棋盘网格来说:
网格线在交叉点处正好截止,不会超出
butt样式让交叉点看起来干净利落如果用了
round或square,线条会在交叉点处互相覆盖,显得杂乱
八、总结
| 问题 | 答案 |
|---|---|
butt 是什么? | 线条端点的平头样式 |
| 效果如何? | 线条精确在终点处截止 |
| 什么时候用? | 需要精确控制线条长度时 |
| 默认值? | 是 Canvas 的默认值 |
| 在棋盘中? | 让网格线交叉点干净利落 |