pin_drop当前位置:知识文库 ❯ 图文
多媒体:剪辑与遮罩 - 完整教程与代码示例
一、教程简介
SVG 剪辑(<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
四、代码示例
示例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>五、浏览器兼容性
提示: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 符号与引用。
本文涉及AI创作
内容由AI创作,请仔细甄别