pin_drop当前位置:知识文库 ❯ 图文

多媒体:剪辑与遮罩 - 完整教程与代码示例

一、教程简介

SVG 剪辑(<clipPath>)和遮罩(<mask>)是控制图形可见区域的两种机制。剪辑使用路径定义硬边界裁剪区域,遮罩使用灰度图像定义半透明遮罩区域。两者都可以实现复杂的图形裁切效果,但原理和效果各有不同。本教程将详细讲解剪辑和遮罩的原理、使用方法和实际应用。


二、核心概念

clipPath 剪辑

  • 使用路径定义裁剪区域

  • 裁剪区域内的内容可见,区域外的内容完全不可见

  • 硬边界,不支持半透明

  • 类似于"剪刀"裁切

mask 遮罩

  • 使用图形的亮度/透明度定义遮罩

  • 白色区域完全可见,黑色区域完全不可见,灰色区域半透明

  • 支持渐变和半透明效果

  • 类似于"蒙版"遮挡

对比

特性 clipPath mask
边界 硬边界 支持半透明
颜色 不使用颜色 使用灰度/透明度
渐变 不支持渐变 支持渐变
性能 更好 较差
适用 精确裁切 柔和过渡

三、语法与用法

clipPath

代码示例

<defs>
  <clipPath id="myClip">
    <circle cx="100" cy="100" r="50" />
  </clipPath>
</defs>
<rect width="200" height="200" fill="#58a6ff" clip-path="url(#myClip)" />

mask

代码示例

<defs>
  <mask id="myMask">
    <circle cx="100" cy="100" r="50" fill="white" />
  </mask>
</defs>
<rect width="200" height="200" fill="#58a6ff" mask="url(#myMask)" />

clipPathUnits / maskContentUnits

说明
userSpaceOnUse 使用用户空间坐标
objectBoundingBox 使用元素边界框比例

四、代码示例

示例1:clipPath 剪辑演示

代码示例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>SVG clipPath 剪辑演示</title>
  <style>
    body {
      margin: 0; padding: 20px;
      background: #0d1117; color: #c9d1d9;
      font-family: 'Segoe UI', sans-serif;
      display: flex; flex-direction: column; align-items: center;
    }
    svg { background: #161b22; border-radius: 8px; border: 1px solid #30363d; }
  </style>
</head>
<body>
  <h1>SVG clipPath 剪辑演示</h1>
  <svg width="750" height="400" viewBox="0 0 750 400">
    <defs>
      <!-- 圆形剪辑 -->
      <clipPath id="clipCircle">
        <circle cx="100" cy="100" r="70" />
      </clipPath>

      <!-- 矩形剪辑 -->
      <clipPath id="clipRect">
        <rect x="30" y="30" width="140" height="140" rx="10" />
      </clipPath>

      <!-- 星形剪辑 -->
      <clipPath id="clipStar">
        <polygon points="250,30 270,90 335,90 280,125 300,190 250,150 200,190 220,125 165,90 230,90" />
      </clipPath>

      <!-- 文字剪辑 -->
      <clipPath id="clipText">
        <text x="500" y="130" font-size="100" font-weight="bold" text-anchor="middle">SVG</text>
      </clipPath>

      <!-- 多形状组合剪辑 -->
      <clipPath id="clipMulti">
        <circle cx="100" cy="300" r="50" />
        <rect x="160" y="250" width="80" height="100" rx="10" />
        <polygon points="300,250 340,350 260,350" />
      </clipPath>
    </defs>

    <!-- 渐变背景 -->
    <defs>
      <linearGradient id="bgGrad" x1="0%" y1="0%" x2="100%" y2="100%">
        <stop offset="0%" stop-color="#e94560" />
        <stop offset="25%" stop-color="#f8b500" />
        <stop offset="50%" stop-color="#3fb950" />
        <stop offset="75%" stop-color="#58a6ff" />
        <stop offset="100%" stop-color="#d2a8ff" />
      </linearGradient>
    </defs>

    <!-- 圆形剪辑 -->
    <text x="100" y="20" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">圆形剪辑</text>
    <rect x="10" y="25" width="180" height="180" fill="url(#bgGrad)" clip-path="url(#clipCircle)" />
    <circle cx="100" cy="100" r="70" fill="none" stroke="#30363d" stroke-dasharray="4" />

    <!-- 矩形剪辑 -->
    <text x="250" y="20" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">矩形剪辑</text>
    <g clip-path="url(#clipRect)">
      <rect x="170" y="25" width="160" height="180" fill="url(#bgGrad)" />
    </g>

    <!-- 星形剪辑 -->
    <text x="400" y="20" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">星形剪辑</text>
    <rect x="165" y="25" width="470" height="180" fill="url(#bgGrad)" clip-path="url(#clipStar)" />

    <!-- 文字剪辑 -->
    <text x="625" y="20" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">文字剪辑</text>
    <rect x="380" y="25" width="490" height="180" fill="url(#bgGrad)" clip-path="url(#clipText)" />

    <!-- 多形状组合 -->
    <text x="200" y="225" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">多形状组合剪辑</text>
    <rect x="50" y="235" width="300" height="150" fill="url(#bgGrad)" clip-path="url(#clipMulti)" />

    <!-- 剪辑动画 -->
    <text x="550" y="225" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">动画剪辑</text>
    <defs>
      <clipPath id="clipAnim">
        <circle cx="550" cy="320" r="60">
          <animate attributeName="r" values="60;80;60" dur="2s" repeatCount="indefinite" />
        </circle>
      </clipPath>
    </defs>
    <rect x="420" y="235" width="260" height="150" fill="url(#bgGrad)" clip-path="url(#clipAnim)" />
  </svg>
</body>
</html>

示例2:mask 遮罩演示

代码示例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>SVG mask 遮罩演示</title>
  <style>
    body {
      margin: 0; padding: 20px;
      background: #1a1a2e; color: #eee;
      font-family: 'Segoe UI', sans-serif;
      display: flex; flex-direction: column; align-items: center;
    }
    svg { background: #16213e; border-radius: 8px; border: 1px solid #333; }
  </style>
</head>
<body>
  <h1>SVG mask 遮罩演示</h1>
  <svg width="700" height="400" viewBox="0 0 700 400">
    <defs>
      <linearGradient id="rainbow" x1="0%" y1="0%" x2="100%" y2="0%">
        <stop offset="0%" stop-color="#e94560" />
        <stop offset="25%" stop-color="#f8b500" />
        <stop offset="50%" stop-color="#3fb950" />
        <stop offset="75%" stop-color="#58a6ff" />
        <stop offset="100%" stop-color="#d2a8ff" />
      </linearGradient>

      <!-- 渐变遮罩(淡出效果) -->
      <mask id="maskFade">
        <linearGradient id="fadeGrad" x1="0%" y1="0%" x2="100%" y2="0%">
          <stop offset="0%" stop-color="white" />
          <stop offset="100%" stop-color="black" />
        </linearGradient>
        <rect width="300" height="200" fill="url(#fadeGrad)" />
      </mask>

      <!-- 径向渐变遮罩(聚光灯) -->
      <mask id="maskSpot">
        <radialGradient id="spotGrad" cx="50%" cy="50%" r="50%">
          <stop offset="0%" stop-color="white" />
          <stop offset="70%" stop-color="white" />
          <stop offset="100%" stop-color="black" />
        </radialGradient>
        <rect width="200" height="200" fill="url(#spotGrad)" />
      </mask>

      <!-- 文字遮罩 -->
      <mask id="maskText">
        <rect width="700" height="100" fill="black" />
        <text x="350" y="80" text-anchor="middle" font-size="80" font-weight="bold" fill="white">MASK</text>
      </mask>

      <!-- 形状遮罩 -->
      <mask id="maskShape">
        <rect width="200" height="200" fill="black" />
        <circle cx="100" cy="80" r="50" fill="white" />
        <rect x="30" y="120" width="140" height="60" rx="10" fill="white" />
      </mask>
    </defs>

    <!-- 渐变淡出 -->
    <text x="150" y="25" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">渐变淡出遮罩</text>
    <rect x="0" y="35" width="300" height="150" fill="url(#rainbow)" mask="url(#maskFade)" />

    <!-- 聚光灯效果 -->
    <text x="500" y="25" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">聚光灯遮罩</text>
    <rect x="400" y="35" width="200" height="150" fill="url(#rainbow)" mask="url(#maskSpot)" />

    <!-- 文字遮罩 -->
    <text x="350" y="215" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">文字遮罩</text>
    <rect x="50" y="225" width="600" height="100" fill="url(#rainbow)" mask="url(#maskText)" />

    <!-- 形状遮罩 -->
    <text x="150" y="350" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">形状遮罩</text>
    <rect x="50" y="355" width="200" height="40" fill="url(#rainbow)" mask="url(#maskShape)" />

    <!-- clipPath vs mask 对比 -->
    <text x="500" y="350" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">clipPath(左) vs mask(右)</text>
    <defs>
      <clipPath id="cmpClip">
        <circle cx="440" cy="385" r="25" />
      </clipPath>
      <mask id="cmpMask">
        <circle cx="540" cy="385" r="25" fill="white" />
      </mask>
    </defs>
    <rect x="400" y="360" width="80" height="40" fill="url(#rainbow)" clip-path="url(#cmpClip)" />
    <rect x="500" y="360" width="80" height="40" fill="url(#rainbow)" mask="url(#cmpMask)" />
  </svg>
</body>
</html>

五、浏览器兼容性

特性 Chrome Firefox Safari Edge IE
<clipPath> 1+ 1.5+ 3+ 12+ 9+
<mask> 1+ 1.5+ 3.2+ 12+ 不支持
clipPath 动画 1+ 1.5+ 3+ 不支持 不支持

提示:IE 不支持 SVG mask,Edge 12+ 支持。


六、注意事项与最佳实践

1. clipPath 使用路径元素

代码示例

<!-- clipPath 内推荐使用基本形状和 path -->
<clipPath id="clip1">
  <circle cx="50" cy="50" r="40" />
  <rect x="80" y="10" width="60" height="80" />
  <path d="M 160 10 L 200 90 L 120 90 Z" />
</clipPath>

2. mask 使用灰度

代码示例

<!-- 白色=可见,黑色=不可见,灰色=半透明 -->
<mask id="mask1">
  <rect width="200" height="200" fill="white" />  <!-- 全部可见 -->
  <circle cx="100" cy="100" r="50" fill="black" /> <!-- 中心不可见 -->
</mask>

3. 性能考虑

clipPath 比 mask 性能更好,不需要半透明效果时优先使用 clipPath。

4. CSS clip-path

代码示例

/* CSS 也可以使用 clip-path */
.element {
  clip-path: circle(50% at 50% 50%);
  clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
  clip-path: url(#myClipPath); /* 引用 SVG clipPath */
}

七、代码规范示例

代码示例

<!-- 推荐:clipPath 定义规范 -->
<defs>
  <clipPath id="clip-avatar" clipPathUnits="objectBoundingBox">
    <circle cx="0.5" cy="0.5" r="0.5" />
  </clipPath>
</defs>

<!-- 推荐:mask 定义规范 -->
<defs>
  <mask id="mask-fade" maskContentUnits="userSpaceOnUse">
    <linearGradient id="fade-mask-grad" x1="0" y1="0" x2="1" y2="0">
      <stop offset="0" stop-color="white" />
      <stop offset="1" stop-color="black" />
    </linearGradient>
    <rect width="300" height="200" fill="url(#fade-mask-grad)" />
  </mask>
</defs>

八、常见问题与解决方案

常见问题

clipPath 内能用 text 吗?

可以,文字轮廓会被用作裁剪路径:

代码示例

<clipPath id="textClip">
  <text x="100" y="100" font-size="80" font-weight="bold">CLIP</text>
</clipPath>
mask 在 IE 不工作?

解决方案:使用 clipPath 替代,或使用 CSS clip-path。

如何实现图片的圆形裁切?

使用 clipPath 定义圆形路径,然后应用到 image 元素:

代码示例

<defs>
  <clipPath id="circleClip">
    <circle cx="100" cy="100" r="80" />
  </clipPath>
</defs>
<image href="photo.jpg" width="200" height="200" clip-path="url(#circleClip)" />
clipPath 和 mask 哪个性能更好?

clipPath 性能更好,因为它只涉及简单的路径裁剪计算。mask 需要计算每个像素的灰度值,性能开销较大。不需要半透明效果时优先使用 clipPath。


九、总结

SVG 剪辑和遮罩是控制图形可见区域的重要机制,关键要点:

  • clipPath:硬边界裁剪,区域外完全不可见

  • mask:灰度遮罩,支持半透明和渐变

  • clipPath 性能更好:不需要半透明时优先使用

  • mask 更灵活:支持渐变淡出、聚光灯等效果

  • 文字剪辑:文字轮廓可作为裁剪路径

  • CSS clip-path:CSS 也可以引用 SVG clipPath

  • 兼容性:mask 不支持 IE,clipPath 兼容性更好

下一教程将介绍 SVG 符号与引用。

标签: SVG剪辑 clipPath SVG遮罩 mask标签 SVG教程 图形裁切

本文涉及AI创作

内容由AI创作,请仔细甄别

list快速访问

上一篇: 多媒体:SVG动画 - 完整教程与代码示例 下一篇: 多媒体:符号与引用 - 完整教程与代码示例

poll相关推荐