ZetCode

JavaScript Canvas miterLimit 教程

最后修改于 2025 年 4 月 3 日

在本文中,我们将探讨 JavaScript 中的 Canvas miterLimit 属性。此属性控制在使用斜接线段连接时如何渲染锐角。理解 miterLimit 对于制作专业质量的线条图至关重要。

基本定义

miterLimit 属性指定了斜接连接可以超出正常线宽的距离。仅当 lineJoin 设置为 'miter' 时才适用。默认值为 10.0。

当两条线以锐角相交时,斜接连接可能会变得非常长。miterLimit 通过在超过限制时将它们转换为斜接连接来防止过长的连接。

默认 miterLimit 行为

此示例显示了具有锐角的默认 miterLimit 行为。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Default miterLimit</title>
</head>
<body>

<canvas id="myCanvas" width="300" height="200"></canvas>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    ctx.lineJoin = 'miter';
    ctx.lineWidth = 10;
    ctx.strokeStyle = 'blue';
    
    ctx.beginPath();
    ctx.moveTo(50, 150);
    ctx.lineTo(150, 50);
    ctx.lineTo(250, 150);
    ctx.stroke();
</script>

</body>
</html>

此代码绘制了一个 V 形,使用了斜接线段连接。默认的 miterLimit 为 10,允许锐角明显超出线宽。

斜接连接在两条线相交处创建一个尖角。这个尖角的长度会根据线之间的角度自动计算。

设置较小的 miterLimit

此示例演示了当 miterLimit 设置得太小时会发生什么。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Small miterLimit</title>
</head>
<body>

<canvas id="myCanvas" width="300" height="200"></canvas>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    ctx.lineJoin = 'miter';
    ctx.miterLimit = 2;
    ctx.lineWidth = 10;
    ctx.strokeStyle = 'red';
    
    ctx.beginPath();
    ctx.moveTo(50, 150);
    ctx.lineTo(150, 50);
    ctx.lineTo(250, 150);
    ctx.stroke();
</script>

</body>
</html>

当 miterLimit 设置为 2 时,锐角会超出此限制并转换为斜接连接。这可以防止斜接变得过长。

miterLimit 值代表了斜接长度与线宽允许的最大比率。当超出此比率时,连接会自动切换为斜接样式。

比较不同的 miterLimit 值

此示例并排比较了三个不同的 miterLimit 值。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>miterLimit Comparison</title>
</head>
<body>

<canvas id="myCanvas" width="500" height="300"></canvas>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    function drawAngle(x, limit) {
        ctx.lineJoin = 'miter';
        ctx.miterLimit = limit;
        ctx.lineWidth = 10;
        ctx.strokeStyle = 'green';
        
        ctx.beginPath();
        ctx.moveTo(x, 200);
        ctx.lineTo(x + 100, 100);
        ctx.lineTo(x + 200, 200);
        ctx.stroke();
        
        ctx.fillText('miterLimit: ' + limit, x + 30, 230);
    }
    
    drawAngle(50, 1);
    drawAngle(200, 5);
    drawAngle(350, 10);
</script>

</body>
</html>

此代码绘制了三个具有不同 miterLimit 值的相同角度。第一个使用 1(变为斜接),第二个使用 5(中度斜接),第三个使用 10。

您可以清楚地看到,较高的 miterLimit 值允许更长的尖角。第一个示例转换为斜接,因为 1 对此角度来说过于严格。

不同角度下的 miterLimit

此示例显示了 miterLimit 如何影响不同大小的角度。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>miterLimit with Angles</title>
</head>
<body>

<canvas id="myCanvas" width="600" height="400"></canvas>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    ctx.font = '12px Arial';
    ctx.textAlign = 'center';
    
    function drawAngle(x, y, angle, limit) {
        const radians = angle * Math.PI / 180;
        const length = 100;
        
        ctx.lineJoin = 'miter';
        ctx.miterLimit = limit;
        ctx.lineWidth = 8;
        ctx.strokeStyle = 'purple';
        
        ctx.beginPath();
        ctx.moveTo(x, y);
        ctx.lineTo(x + length * Math.cos(radians/2), 
                  y - length * Math.sin(radians/2));
        ctx.lineTo(x + length * Math.cos(radians/2) * 2, y);
        ctx.stroke();
        
        ctx.fillText(angle + '°', x + length * Math.cos(radians/2), y + 20);
    }
    
    // Draw angles from 10° to 170° in 20° increments
    for (let i = 0; i < 9; i++) {
        const angle = 10 + i * 20;
        drawAngle(50 + i * 60, 150, angle, 4);
    }
</script>

</body>
</html>

此示例绘制了从 10° 到 170° 的角度,miterLimit 固定为 4。更锐利的角度(数值较小)将超出此限制并转换为斜接。

您可以观察到,随着角度变得越来越尖锐,斜接连接也会变得越来越长。在大约 30° 时,miterLimit 会被超出,连接会变为斜接。

miterLimit 的实际应用

此示例展示了调整 miterLimit 的一个实际用例。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Practical miterLimit</title>
</head>
<body>

<canvas id="myCanvas" width="500" height="300"></canvas>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    // Without miterLimit control
    ctx.lineJoin = 'miter';
    ctx.lineWidth = 15;
    ctx.strokeStyle = 'rgba(255,0,0,0.5)';
    
    ctx.beginPath();
    ctx.moveTo(50, 100);
    ctx.lineTo(150, 50);
    ctx.lineTo(250, 100);
    ctx.lineTo(350, 50);
    ctx.lineTo(450, 100);
    ctx.stroke();
    
    // With miterLimit control
    ctx.lineJoin = 'miter';
    ctx.miterLimit = 4;
    ctx.lineWidth = 15;
    ctx.strokeStyle = 'rgba(0,0,255,0.5)';
    
    ctx.beginPath();
    ctx.moveTo(50, 200);
    ctx.lineTo(150, 150);
    ctx.lineTo(250, 200);
    ctx.lineTo(350, 150);
    ctx.lineTo(450, 200);
    ctx.stroke();
</script>

</body>
</html>

此示例比较了两条锯齿线 - 一条使用默认 miterLimit,另一条使用 miterLimit 设置为 4。第一条线具有极长的斜接连接。

第二条线保持了尖锐的角,但防止了过长的长度。这表明 miterLimit 如何改善复杂路径的外观。

来源

MDN Canvas miterLimit 文档

在本文中,我们深入探讨了 miterLimit 属性。这个经常被忽视的属性对于控制画布绘图中锐角的出现至关重要。

作者

我叫 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直在撰写编程文章。至今,我已撰写了 1,400 多篇文章和 8 本电子书。我在编程教学方面拥有超过十年的经验。

列出 所有 JS Canvas 教程