ZetCode

JavaScript Canvas isPointInStroke 教程

最后修改于 2025 年 4 月 3 日

在本文中,我们将探讨 JavaScript 中的 Canvas isPointInStroke 方法。此方法可检测一个点是否位于描边路径内。对于创建具有命中检测功能的交互式 Canvas 应用程序至关重要。

基本定义

isPointInStroke 方法检查一个点是否在路径的描边上。如果该点位于描边区域内,则返回 true,它会考虑当前的描边样式、线宽和其他描边属性。

此方法对于需要检测用户是否单击了描边路径的交互式应用程序很有用。它适用于简单形状和复杂路径。

isPointInStroke 的基本用法

此示例演示了如何检测对描边矩形的单击。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Basic isPointInStroke</title>
</head>
<body>

<canvas id="myCanvas" width="300" height="200"></canvas>
<p id="output">Click on the canvas</p>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    const output = document.getElementById('output');
    
    ctx.strokeStyle = 'blue';
    ctx.lineWidth = 10;
    ctx.strokeRect(50, 50, 200, 100);
    
    canvas.addEventListener('click', (e) => {
        const rect = canvas.getBoundingClientRect();
        const x = e.clientX - rect.left;
        const y = e.clientY - rect.top;
        
        ctx.beginPath();
        ctx.rect(50, 50, 200, 100);
        
        if (ctx.isPointInStroke(x, y)) {
            output.textContent = 'Clicked on the stroke!';
        } else {
            output.textContent = 'Clicked outside the stroke';
        }
    });
</script>

</body>
</html>

此示例创建了一个带有 10px 描边的蓝色矩形。单击 Canvas 时,它会使用 isPointInStroke 检查单击是否在描边上。

单击坐标被转换为 Canvas 空间。在检查之前,我们重新创建了路径以确保准确的命中检测。结果显示在 Canvas 下方。

检测自定义路径中的点

此示例演示了如何检测描边自定义路径中的点。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Custom Path Detection</title>
</head>
<body>

<canvas id="myCanvas" width="300" height="200"></canvas>
<p id="output">Click on the triangle</p>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    const output = document.getElementById('output');
    
    // Draw triangle
    ctx.beginPath();
    ctx.moveTo(150, 50);
    ctx.lineTo(50, 150);
    ctx.lineTo(250, 150);
    ctx.closePath();
    
    ctx.strokeStyle = 'red';
    ctx.lineWidth = 8;
    ctx.stroke();
    
    canvas.addEventListener('click', (e) => {
        const rect = canvas.getBoundingClientRect();
        const x = e.clientX - rect.left;
        const y = e.clientY - rect.top;
        
        // Recreate path for detection
        ctx.beginPath();
        ctx.moveTo(150, 50);
        ctx.lineTo(50, 150);
        ctx.lineTo(250, 150);
        ctx.closePath();
        
        if (ctx.isPointInStroke(x, y)) {
            output.textContent = 'Clicked on the triangle stroke!';
        } else {
            output.textContent = 'Clicked outside the stroke';
        }
    });
</script>

</body>
</html>

此示例创建了一个带有 8px 描边的红色三角形。单击处理程序会重新创建路径并检查单击是否在描边上。

请注意,在调用 isPointInStroke 之前,我们必须重新创建完全相同的路径。该方法仅适用于 Canvas 状态中的当前路径。

交互式描边检测

此示例创建了一个交互式应用程序,当鼠标悬停在描边圆上时会突出显示该圆。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Interactive Stroke Detection</title>
</head>
<body>

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

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    function drawCircle(highlight = false) {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        ctx.beginPath();
        ctx.arc(150, 150, 100, 0, Math.PI * 2);
        
        ctx.strokeStyle = highlight ? 'green' : 'blue';
        ctx.lineWidth = 15;
        ctx.stroke();
    }
    
    drawCircle();
    
    canvas.addEventListener('mousemove', (e) => {
        const rect = canvas.getBoundingClientRect();
        const x = e.clientX - rect.left;
        const y = e.clientY - rect.top;
        
        ctx.beginPath();
        ctx.arc(150, 150, 100, 0, Math.PI * 2);
        
        if (ctx.isPointInStroke(x, y)) {
            drawCircle(true);
        } else {
            drawCircle(false);
        }
    });
</script>

</body>
</html>

此示例创建了一个圆,当鼠标悬停在其描边上时,该圆会改变颜色。mousemove 事件会针对描边检查光标位置。

drawCircle 函数会根据鼠标是否在描边上来绘制不同颜色的圆。这会产生视觉反馈效果。

检测文本描边中的点

此示例演示了如何检测描边文本中的单击。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Text Stroke Detection</title>
</head>
<body>

<canvas id="myCanvas" width="400" height="200"></canvas>
<p id="output">Click on the text</p>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    const output = document.getElementById('output');
    
    ctx.font = '48px Arial';
    ctx.strokeStyle = 'purple';
    ctx.lineWidth = 3;
    ctx.strokeText('Click Me', 50, 120);
    
    canvas.addEventListener('click', (e) => {
        const rect = canvas.getBoundingClientRect();
        const x = e.clientX - rect.left;
        const y = e.clientY - rect.top;
        
        ctx.beginPath();
        ctx.font = '48px Arial';
        ctx.strokeText('Click Me', 50, 120);
        
        if (ctx.isPointInStroke(x, y)) {
            output.textContent = 'Clicked on the text stroke!';
        } else {
            output.textContent = 'Clicked outside the text';
        }
    });
</script>

</body>
</html>

此示例创建了描边文本并检测了对文本的单击。文本使用 3px 的紫色描边通过 strokeText 绘制。

在检查单击时,我们必须使用相同的字体和位置重新创建完全相同的文本路径。该方法与文本路径一样适用于其他路径。

高级:检测复杂路径中的点

此示例演示了如何检测带有曲线的复杂描边路径中的点。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Complex Path Detection</title>
</head>
<body>

<canvas id="myCanvas" width="500" height="300"></canvas>
<p id="output">Click on the path</p>

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    const output = document.getElementById('output');
    
    // Draw complex path
    ctx.beginPath();
    ctx.moveTo(50, 150);
    ctx.lineTo(150, 50);
    ctx.quadraticCurveTo(250, 50, 350, 150);
    ctx.bezierCurveTo(370, 200, 430, 200, 450, 150);
    ctx.lineTo(400, 250);
    ctx.closePath();
    
    ctx.strokeStyle = 'orange';
    ctx.lineWidth = 10;
    ctx.stroke();
    
    canvas.addEventListener('click', (e) => {
        const rect = canvas.getBoundingClientRect();
        const x = e.clientX - rect.left;
        const y = e.clientY - rect.top;
        
        // Recreate complex path
        ctx.beginPath();
        ctx.moveTo(50, 150);
        ctx.lineTo(150, 50);
        ctx.quadraticCurveTo(250, 50, 350, 150);
        ctx.bezierCurveTo(370, 200, 430, 200, 450, 150);
        ctx.lineTo(400, 250);
        ctx.closePath();
        
        if (ctx.isPointInStroke(x, y)) {
            output.textContent = 'Clicked on the complex path stroke!';
        } else {
            output.textContent = 'Clicked outside the path';
        }
    });
</script>

</body>
</html>

此示例创建了一个包含直线、二次曲线和贝塞尔曲线的复杂路径。该路径用粗橙色线描边。

单击检测与简单路径的工作方式相同,但它证明了 isPointInStroke 可以准确地处理带有曲线的复杂路径。

来源

MDN isPointInStroke 文档

在本文中,我们探讨了用于检测 Canvas 描边中点的 isPointInStroke 方法。此强大功能可在描边路径上实现精确命中检测的交互式 Canvas 应用程序。

作者

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

列出 所有 JS Canvas 教程