pin_drop当前位置:知识文库 ❯ 图文
多媒体:SVG滤镜 - 完整教程与代码示例
一、教程简介
SVG 滤镜是对图形元素应用视觉效果的强大机制。通过 <filter> 元素和各种滤镜原语(filter primitives),可以实现模糊、阴影、光照、色彩变换、形态学操作等各种效果。本教程将详细讲解 SVG 滤镜的创建、常用滤镜原语的使用和实际应用。
二、核心概念
filter 元素
滤镜定义在 <defs> 中的 <filter> 元素内,通过 filter="url(#id)" 引用。
滤镜原语
每个滤镜原语以 fe 开头,代表一个图像处理操作。多个原语可以串联使用。
滤镜区域
代码示例
<filter id="myFilter" x="-10%" y="-10%" width="120%" height="120%">
<!-- 滤镜原语 -->
</filter>三、语法与用法
常用滤镜原语
四、代码示例
示例1:常用滤镜效果演示
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVG 滤镜效果演示</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;
}
.grid {
display: grid; grid-template-columns: repeat(3, 1fr);
gap: 15px; max-width: 750px;
}
.card {
background: #161b22; border: 1px solid #30363d;
border-radius: 8px; padding: 12px; text-align: center;
}
.card h3 { color: #58a6ff; font-size: 13px; margin: 0 0 8px; }
svg { background: #0d1117; border-radius: 4px; }
</style>
</head>
<body>
<h1>SVG 滤镜效果演示</h1>
<div class="grid">
<!-- 高斯模糊 -->
<div class="card">
<h3>feGaussianBlur 模糊</h3>
<svg width="220" height="120" viewBox="0 0 220 120">
<defs>
<filter id="blur1">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" />
</filter>
</defs>
<text x="110" y="30" text-anchor="middle" font-size="12" fill="#8b949e">原图</text>
<circle cx="70" cy="70" r="25" fill="#e94560" />
<circle cx="110" cy="70" r="25" fill="#58a6ff" />
<circle cx="90" cy="55" r="25" fill="#3fb950" opacity="0.7" />
<text x="110" y="115" text-anchor="middle" font-size="10" fill="#8b949e">模糊后</text>
<g filter="url(#blur1)" transform="translate(0,-5)">
<circle cx="70" cy="70" r="25" fill="#e94560" />
<circle cx="110" cy="70" r="25" fill="#58a6ff" />
<circle cx="90" cy="55" r="25" fill="#3fb950" opacity="0.7" />
</g>
</svg>
</div>
<!-- 投影阴影 -->
<div class="card">
<h3>feDropShadow 阴影</h3>
<svg width="220" height="120" viewBox="0 0 220 120">
<defs>
<filter id="shadow1">
<feDropShadow dx="3" dy="3" stdDeviation="3" flood-color="#000" flood-opacity="0.5" />
</filter>
</defs>
<rect x="30" y="25" width="70" height="70" rx="10" fill="#58a6ff" filter="url(#shadow1)" />
<circle cx="160" cy="60" r="35" fill="#e94560" filter="url(#shadow1)" />
</svg>
</div>
<!-- 颜色矩阵 -->
<div class="card">
<h3>feColorMatrix 灰度</h3>
<svg width="220" height="120" viewBox="0 0 220 120">
<defs>
<filter id="gray1">
<feColorMatrix type="saturate" values="0" />
</filter>
</defs>
<rect x="20" y="20" width="80" height="80" rx="8" fill="#e94560" />
<rect x="120" y="20" width="80" height="80" rx="8" fill="#e94560" filter="url(#gray1)" />
<text x="60" y="110" text-anchor="middle" font-size="10" fill="#8b949e">原图</text>
<text x="160" y="110" text-anchor="middle" font-size="10" fill="#8b949e">灰度</text>
</svg>
</div>
<!-- 噪声纹理 -->
<div class="card">
<h3>feTurbulence 噪声</h3>
<svg width="220" height="120" viewBox="0 0 220 120">
<defs>
<filter id="turb1">
<feTurbulence type="fractalNoise" baseFrequency="0.05" numOctaves="3" />
</filter>
<filter id="turb2">
<feTurbulence type="turbulence" baseFrequency="0.02" numOctaves="2" />
</filter>
</defs>
<rect x="10" y="10" width="95" height="100" rx="4" filter="url(#turb1)" />
<rect x="115" y="10" width="95" height="100" rx="4" filter="url(#turb2)" />
<text x="57" y="118" text-anchor="middle" font-size="9" fill="#8b949e">fractalNoise</text>
<text x="162" y="118" text-anchor="middle" font-size="9" fill="#8b949e">turbulence</text>
</svg>
</div>
<!-- 形态学 -->
<div class="card">
<h3>feMorphology 膨胀/腐蚀</h3>
<svg width="220" height="120" viewBox="0 0 220 120">
<defs>
<filter id="dilate1">
<feMorphology operator="dilate" radius="2" />
</filter>
<filter id="erode1">
<feMorphology operator="erode" radius="1" />
</filter>
</defs>
<text x="37" y="40" text-anchor="middle" font-size="22" font-weight="bold" fill="#58a6ff">SVG</text>
<text x="110" y="40" text-anchor="middle" font-size="22" font-weight="bold" fill="#58a6ff" filter="url(#dilate1)">SVG</text>
<text x="183" y="40" text-anchor="middle" font-size="22" font-weight="bold" fill="#58a6ff" filter="url(#erode1)">SVG</text>
<text x="37" y="60" text-anchor="middle" font-size="9" fill="#8b949e">原图</text>
<text x="110" y="60" text-anchor="middle" font-size="9" fill="#8b949e">膨胀</text>
<text x="183" y="60" text-anchor="middle" font-size="9" fill="#8b949e">腐蚀</text>
<rect x="20" y="75" width="55" height="30" rx="4" fill="none" stroke="#3fb950" stroke-width="2" />
<rect x="82" y="75" width="55" height="30" rx="4" fill="none" stroke="#3fb950" stroke-width="2" filter="url(#dilate1)" />
<rect x="145" y="75" width="55" height="30" rx="4" fill="none" stroke="#3fb950" stroke-width="2" filter="url(#erode1)" />
</svg>
</div>
<!-- 发光效果 -->
<div class="card">
<h3>发光效果 (Blur+Merge)</h3>
<svg width="220" height="120" viewBox="0 0 220 120">
<defs>
<filter id="glow1" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="4" result="blur" />
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<text x="110" y="50" text-anchor="middle" font-size="30" font-weight="bold" fill="#58a6ff" filter="url(#glow1)">
GLOW
</text>
<circle cx="70" cy="85" r="15" fill="#e94560" filter="url(#glow1)" />
<circle cx="110" cy="85" r="15" fill="#3fb950" filter="url(#glow1)" />
<circle cx="150" cy="85" r="15" fill="#f8b500" filter="url(#glow1)" />
</svg>
</div>
</div>
</body>
</html>示例2:高级滤镜效果
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>高级滤镜效果</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 高级滤镜效果</h1>
<svg width="700" height="350" viewBox="0 0 700 350">
<defs>
<!-- 内阴影效果 -->
<filter id="innerShadow" x="-10%" y="-10%" width="120%" height="120%">
<feComponentTransfer in="SourceAlpha">
<feFuncA type="table" tableValues="1 0" />
</feComponentTransfer>
<feGaussianBlur stdDeviation="3" />
<feOffset dx="3" dy="3" result="offsetblur" />
<feFlood flood-color="#000" flood-opacity="0.5" result="color" />
<feComposite in2="offsetblur" operator="in" />
<feComposite in2="SourceAlpha" operator="in" />
<feMerge>
<feMergeNode in="SourceGraphic" />
<feMergeNode />
</feMerge>
</filter>
<!-- 浮雕效果 -->
<filter id="emboss">
<feConvolveMatrix order="3" kernelMatrix="-2 -1 0 -1 1 1 0 1 2" />
</filter>
<!-- 描边效果 -->
<filter id="outline" x="-5%" y="-5%" width="110%" height="110%">
<feMorphology in="SourceAlpha" operator="dilate" radius="2" result="dilated" />
<feFlood flood-color="#e94560" result="color" />
<feComposite in="color" in2="dilated" operator="in" result="outline" />
<feMerge>
<feMergeNode in="outline" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
<!-- 水波纹效果 -->
<filter id="ripple">
<feTurbulence type="turbulence" baseFrequency="0.01 0.1" numOctaves="1" result="turb">
<animate attributeName="baseFrequency" values="0.01 0.1;0.02 0.12;0.01 0.1" dur="4s" repeatCount="indefinite" />
</feTurbulence>
<feDisplacementMap in="SourceGraphic" in2="turb" scale="8" />
</filter>
</defs>
<!-- 内阴影 -->
<text x="100" y="30" text-anchor="middle" font-size="12" fill="#58a6ff">内阴影</text>
<rect x="20" y="40" width="160" height="80" rx="10" fill="#1f2937" filter="url(#innerShadow)" />
<!-- 浮雕 -->
<text x="310" y="30" text-anchor="middle" font-size="12" fill="#58a6ff">浮雕</text>
<g filter="url(#emboss)">
<rect x="220" y="40" width="80" height="80" rx="8" fill="#58a6ff" />
<circle cx="360" cy="80" r="35" fill="#3fb950" />
</g>
<!-- 描边效果 -->
<text x="530" y="30" text-anchor="middle" font-size="12" fill="#58a6ff">描边效果</text>
<text x="530" y="95" text-anchor="middle" font-size="36" font-weight="bold" fill="#58a6ff" filter="url(#outline)">
OUTLINE
</text>
<!-- 水波纹 -->
<text x="350" y="165" text-anchor="middle" font-size="12" fill="#58a6ff">水波纹动画</text>
<text x="350" y="230" text-anchor="middle" font-size="42" font-weight="bold" fill="#3fb950" filter="url(#ripple)">
RIPPLE
</text>
<!-- 复合滤镜 -->
<text x="350" y="290" text-anchor="middle" font-size="12" fill="#58a6ff">复合滤镜(模糊+阴影+发光)</text>
<defs>
<filter id="complex" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur in="SourceAlpha" stdDeviation="5" result="blur" />
<feOffset in="blur" dx="4" dy="4" result="offsetBlur" />
<feFlood flood-color="#000" flood-opacity="0.4" result="color" />
<feComposite in="color" in2="offsetBlur" operator="in" result="shadow" />
<feGaussianBlur in="SourceGraphic" stdDeviation="2" result="glowBlur" />
<feMerge>
<feMergeNode in="shadow" />
<feMergeNode in="glowBlur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<rect x="220" y="300" width="120" height="40" rx="20" fill="#58a6ff" filter="url(#complex)" />
<text x="280" y="325" text-anchor="middle" font-size="14" fill="#fff" filter="url(#complex)">Button</text>
<circle cx="450" cy="320" r="25" fill="#e94560" filter="url(#complex)" />
<circle cx="530" cy="320" r="25" fill="#3fb950" filter="url(#complex)" />
<circle cx="610" cy="320" r="25" fill="#f8b500" filter="url(#complex)" />
</svg>
</body>
</html>五、浏览器兼容性
提示:
feDropShadow是较新的简写滤镜,Firefox 不支持,可使用 feGaussianBlur + feOffset + feFlood + feComposite 替代。
六、注意事项与最佳实践
1. 滤镜区域要足够大
代码示例
<!-- 模糊和阴影可能超出元素边界,需要扩大滤镜区域 -->
<filter id="myFilter" x="-20%" y="-20%" width="140%" height="140%">2. 滤镜性能
滤镜计算开销较大,避免在大量元素上同时使用复杂滤镜。
3. feDropShadow 兼容性
代码示例
<!-- 兼容写法(替代 feDropShadow) -->
<filter id="shadow">
<feGaussianBlur in="SourceAlpha" stdDeviation="3" />
<feOffset dx="3" dy="3" />
<feComponentTransfer>
<feFuncA type="linear" slope="0.5" />
</feComponentTransfer>
<feMerge>
<feMergeNode />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>4. 滤镜串联
代码示例
<filter id="combined">
<feGaussianBlur in="SourceGraphic" stdDeviation="2" result="blurred" />
<feColorMatrix in="blurred" type="saturate" values="2" result="saturated" />
<feOffset in="saturated" dx="2" dy="2" result="offset" />
<feMerge>
<feMergeNode in="offset" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>七、代码规范示例
代码示例
<!-- 推荐:滤镜定义规范 -->
<defs>
<!-- 使用语义化 ID -->
<filter id="filter-card-shadow" x="-10%" y="-10%" width="120%" height="130%">
<feDropShadow dx="0" dy="4" stdDeviation="6" flood-color="#000" flood-opacity="0.15" />
</filter>
<filter id="filter-glow-blue" x="-30%" y="-30%" width="160%" height="160%">
<feGaussianBlur in="SourceGraphic" stdDeviation="4" result="blur" />
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>八、常见问题与解决方案
常见问题
滤镜效果被裁剪?
原因是滤镜区域不够大。解决方案是增大 filter 的 x/y/width/height 属性值,确保滤镜效果有足够的空间显示。
feDropShadow 在 Firefox 不工作?
解决方案是使用 feGaussianBlur + feOffset + feFlood + feComposite 组合替代 feDropShadow,这样可以确保跨浏览器兼容性。
滤镜性能差?
解决方案:减少 stdDeviation 值、减少滤镜串联数量、避免在动画元素上使用滤镜。复杂滤镜会显著影响渲染性能。
如何实现发光效果?
使用 feGaussianBlur 模糊原图,然后用 feMerge 将模糊结果和原图合并,即可实现发光效果。需要扩大滤镜区域以避免发光被裁剪。
九、总结
SVG 滤镜是创建高级视觉效果的核心工具,关键要点:
-
filter:定义滤镜,通过 url(#id) 引用
-
feGaussianBlur:高斯模糊,最常用的滤镜
-
feDropShadow:投影阴影(注意兼容性)
-
feColorMatrix:颜色矩阵变换,实现灰度、反色等
-
feTurbulence:噪声纹理
-
feMerge:合并多个滤镜结果
-
滤镜区域:确保足够大以容纳效果
-
性能注意:滤镜计算开销大,谨慎使用
下一教程将介绍 SVG 动画。
本文涉及AI创作
内容由AI创作,请仔细甄别