ZetCode

JavaScript Canvas 裁剪教程

最后修改于 2025 年 4 月 3 日

在本文中,我们探索 JavaScript Canvas 中的裁剪方法。裁剪路径允许您将绘图限制在画布的特定区域。这种强大的技术能够实现创意效果和优化渲染。

基本定义

Canvas 裁剪是定义绘图操作可见区域的过程。在裁剪路径之外绘制的任何内容都不会显示。裁剪路径就像后续绘图操作的蒙版。

主要的裁剪方法是 clip,它使用当前路径作为裁剪区域。可以使用路径操作组合多个裁剪路径。可以保存和恢复裁剪区域与画布状态一起。

基本裁剪用法

本示例演示了如何创建简单的圆形裁剪区域。

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

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

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    // Create circular clipping path
    ctx.beginPath();
    ctx.arc(150, 100, 80, 0, Math.PI * 2);
    ctx.clip();
    
    // Draw rectangle (only visible inside circle)
    ctx.fillStyle = 'blue';
    ctx.fillRect(0, 0, 300, 200);
</script>

</body>
</html>

在这个基本示例中,我们创建了一个圆形路径并调用了 clip。这会将裁剪区域设置为圆形。紧随其后的蓝色矩形仅在此圆形区域内可见。

裁剪路径会一直存在,直到画布状态被恢复或重置。所有后续的绘图操作都将被裁剪到此区域。

使用复杂路径进行裁剪

本示例展示了如何创建星形裁剪区域。

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

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

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    // Create star-shaped clipping path
    ctx.beginPath();
    ctx.moveTo(150, 50);
    ctx.lineTo(175, 125);
    ctx.lineTo(250, 125);
    ctx.lineTo(190, 175);
    ctx.lineTo(210, 250);
    ctx.lineTo(150, 200);
    ctx.lineTo(90, 250);
    ctx.lineTo(110, 175);
    ctx.lineTo(50, 125);
    ctx.lineTo(125, 125);
    ctx.closePath();
    ctx.clip();
    
    // Draw gradient (only visible inside star)
    const gradient = ctx.createLinearGradient(0, 0, 300, 300);
    gradient.addColorStop(0, 'red');
    gradient.addColorStop(1, 'yellow');
    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, 300, 300);
</script>

</body>
</html>

在这里,我们使用多个 lineTo 调用创建了一个复杂的星形路径。clip 方法将此路径转换为裁剪区域。

紧随其后的渐变填充仅在星形形状内可见。这表明任何复杂路径都可以用作裁剪蒙版。

多个裁剪区域

本示例展示了如何组合多个裁剪路径。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Multiple Clipping Regions</title>
</head>
<body>

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

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    // First clipping circle
    ctx.beginPath();
    ctx.arc(100, 100, 60, 0, Math.PI * 2);
    ctx.clip();
    
    // Second clipping circle (intersects with first)
    ctx.beginPath();
    ctx.arc(200, 100, 60, 0, Math.PI * 2);
    ctx.clip();
    
    // Draw pattern (only visible in intersection)
    ctx.fillStyle = 'green';
    for (let x = 0; x < 300; x += 20) {
        for (let y = 0; y < 200; y += 20) {
            ctx.fillRect(x, y, 10, 10);
        }
    }
</script>

</body>
</html>

本示例创建了两个重叠的圆形裁剪区域。有效的裁剪区域是两个圆形的交集,即它们重叠的部分。

网格图案仅在两个裁剪圆相交的地方绘制。这表明多次调用 clip 可以组合成复杂的区域。

使用 Save/Restore 进行裁剪

本示例演示了如何使用 save/restore 来管理裁剪状态。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Save/Restore Clip</title>
</head>
<body>

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

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    // Save initial state
    ctx.save();
    
    // Create first clipping region (left circle)
    ctx.beginPath();
    ctx.arc(100, 100, 80, 0, Math.PI * 2);
    ctx.clip();
    
    // Draw in first region
    ctx.fillStyle = 'rgba(255, 0, 0, 0.5)';
    ctx.fillRect(0, 0, 400, 200);
    
    // Restore state and create second clipping region
    ctx.restore();
    ctx.beginPath();
    ctx.arc(300, 100, 80, 0, Math.PI * 2);
    ctx.clip();
    
    // Draw in second region
    ctx.fillStyle = 'rgba(0, 0, 255, 0.5)';
    ctx.fillRect(0, 0, 400, 200);
</script>

</body>
</html>

在这里,我们使用 saverestore 来管理不同的裁剪状态。第一个裁剪圆是在保存状态后创建的。

绘制完成后,我们恢复到原始状态并创建第二个裁剪圆。这使我们能够在不重叠的情况下拥有独立的裁剪区域。

文本裁剪效果

本示例使用文本作为裁剪路径创建了一个裁剪效果。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Text Clipping Effect</title>
</head>
<body>

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

<script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    // Set large font for clipping
    ctx.font = 'bold 100px Arial';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    
    // Create text clipping path
    ctx.beginPath();
    ctx.fillText('CLIP', 250, 100);
    ctx.clip();
    
    // Draw gradient inside text
    const gradient = ctx.createLinearGradient(0, 0, 500, 0);
    gradient.addColorStop(0, 'red');
    gradient.addColorStop(0.5, 'yellow');
    gradient.addColorStop(1, 'blue');
    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, 500, 200);
</script>

</body>
</html>

这个创意示例使用文本作为裁剪路径。fillText 方法创建了文本路径,然后用于裁剪。

紧随其后的渐变填充仅在文本字符内部可见。这种技术可用于创建有趣的文本效果和蒙版。

来源

MDN Canvas clip 文档

在本文中,我们探讨了在 HTML Canvas 上使用裁剪路径的各种技术。掌握裁剪功能可以实现高级图形效果和 Web 应用程序的优化渲染。

作者

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

列出 所有 JS Canvas 教程