pin_drop当前位置:知识文库 ❯ 图文
多媒体:SVG动画 - 完整教程与代码示例
一、教程简介
SVG 提供了多种动画实现方式:SMIL 动画(<animate>、<animateTransform> 等)、CSS 动画和 JavaScript 动画。SMIL 是 SVG 原生的动画机制,无需 JavaScript 即可实现属性动画和变换动画。CSS 动画则利用 CSS 的 transition 和 animation 属性。本教程将详细讲解 SVG 动画的各种实现方法。
二、核心概念
动画方式对比
SMIL 动画元素
三、语法与用法
animate - 属性动画
代码示例
<circle cx="50" cy="50" r="20" fill="#58a6ff">
<animate attributeName="r" from="20" to="40" dur="2s" repeatCount="indefinite" />
</circle>animateTransform - 变换动画
代码示例
<rect x="50" y="50" width="50" height="50">
<animateTransform attributeName="transform" type="rotate"
from="0 75 75" to="360 75 75" dur="3s" repeatCount="indefinite" />
</rect>
type 类型:translate、rotate、scale、skewX、skewY
animateMotion - 路径运动
代码示例
<circle r="5" fill="#e94560">
<animateMotion path="M 50 100 Q 200 20 350 100" dur="3s" repeatCount="indefinite" />
</circle>CSS 动画
代码示例
@keyframes pulse {
0% { r: 20; }
50% { r: 35; }
100% { r: 20; }
}
.pulse-circle {
animation: pulse 2s ease-in-out infinite;
}四、代码示例
示例1:SMIL 动画全面演示
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVG SMIL 动画演示</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 SMIL 动画演示</h1>
<svg width="750" height="500" viewBox="0 0 750 500">
<!-- 1. 属性动画 - 脉冲圆 -->
<text x="125" y="25" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">属性动画</text>
<circle cx="125" cy="100" r="30" fill="#e94560" opacity="0.8">
<animate attributeName="r" values="30;45;30" dur="2s" repeatCount="indefinite" />
<animate attributeName="opacity" values="0.8;0.4;0.8" dur="2s" repeatCount="indefinite" />
</circle>
<!-- 2. 颜色动画 -->
<text x="375" y="25" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">颜色动画</text>
<circle cx="375" cy="100" r="35">
<animate attributeName="fill" values="#e94560;#f8b500;#3fb950;#58a6ff;#d2a8ff;#e94560" dur="5s" repeatCount="indefinite" />
</circle>
<!-- 3. 旋转动画 -->
<text x="625" y="25" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">旋转动画</text>
<g>
<rect x="590" y="65" width="70" height="70" rx="8" fill="#58a6ff" opacity="0.8">
<animateTransform attributeName="transform" type="rotate"
from="0 625 100" to="360 625 100" dur="4s" repeatCount="indefinite" />
</rect>
</g>
<!-- 4. 缩放动画 -->
<text x="125" y="175" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">缩放动画</text>
<g>
<rect x="90" y="195" width="70" height="70" rx="8" fill="#3fb950" opacity="0.8">
<animateTransform attributeName="transform" type="scale"
values="1;1.3;1" dur="2s" repeatCount="indefinite" additive="sum" />
</rect>
</g>
<!-- 5. 平移动画 -->
<text x="375" y="175" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">平移动画</text>
<circle cx="300" cy="230" r="20" fill="#f8b500">
<animateTransform attributeName="transform" type="translate"
values="0,0;150,0;0,0" dur="3s" repeatCount="indefinite" />
</circle>
<!-- 6. 路径运动 -->
<text x="625" y="175" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">路径运动</text>
<path d="M 550 250 Q 625 180 700 250 Q 625 320 550 250" fill="none" stroke="#30363d" stroke-dasharray="4" />
<circle r="8" fill="#d2a8ff">
<animateMotion path="M 550 250 Q 625 180 700 250 Q 625 320 550 250" dur="4s" repeatCount="indefinite" />
</circle>
<!-- 7. 描边动画 -->
<text x="125" y="325" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">描边动画</text>
<text x="125" y="390" text-anchor="middle" font-size="40" font-weight="bold" fill="none" stroke="#e94560" stroke-width="2">
SVG
<animate attributeName="stroke-dashoffset" from="300" to="0" dur="3s" repeatCount="indefinite" />
<set attributeName="stroke-dasharray" to="300" />
</text>
<!-- 8. 多重动画 -->
<text x="375" y="325" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">多重动画</text>
<circle cx="375" cy="400" r="25" fill="#58a6ff">
<animate attributeName="r" values="25;35;25" dur="2s" repeatCount="indefinite" />
<animate attributeName="fill" values="#58a6ff;#e94560;#58a6ff" dur="2s" repeatCount="indefinite" />
<animateTransform attributeName="transform" type="rotate"
from="0 375 400" to="360 375 400" dur="6s" repeatCount="indefinite" />
</circle>
<!-- 9. 弹跳球 -->
<text x="625" y="325" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">弹跳球</text>
<circle cx="625" cy="350" r="15" fill="#3fb950">
<animateTransform attributeName="transform" type="translate"
values="0,0; 0,80; 0,0" dur="1s" repeatCount="indefinite"
keyTimes="0;0.5;1" keySplines="0.5 0 1 1;0 0 0.5 1" calcMode="spline" />
<animate attributeName="r" values="15;13;15" dur="1s" repeatCount="indefinite"
keyTimes="0;0.5;1" />
</circle>
<line x1="560" y1="445" x2="690" y2="445" stroke="#30363d" stroke-width="2" />
<!-- 10. 加载动画 -->
<text x="375" y="470" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">加载动画</text>
<g transform="translate(375, 490)">
<circle r="4" fill="#e94560" transform="rotate(0) translate(15,0)">
<animate attributeName="opacity" values="1;0.2;1" dur="1.2s" repeatCount="indefinite" begin="0s" />
</circle>
<circle r="4" fill="#f8b500" transform="rotate(60) translate(15,0)">
<animate attributeName="opacity" values="1;0.2;1" dur="1.2s" repeatCount="indefinite" begin="0.2s" />
</circle>
<circle r="4" fill="#3fb950" transform="rotate(120) translate(15,0)">
<animate attributeName="opacity" values="1;0.2;1" dur="1.2s" repeatCount="indefinite" begin="0.4s" />
</circle>
<circle r="4" fill="#58a6ff" transform="rotate(180) translate(15,0)">
<animate attributeName="opacity" values="1;0.2;1" dur="1.2s" repeatCount="indefinite" begin="0.6s" />
</circle>
<circle r="4" fill="#d2a8ff" transform="rotate(240) translate(15,0)">
<animate attributeName="opacity" values="1;0.2;1" dur="1.2s" repeatCount="indefinite" begin="0.8s" />
</circle>
<circle r="4" fill="#f78166" transform="rotate(300) translate(15,0)">
<animate attributeName="opacity" values="1;0.2;1" dur="1.2s" repeatCount="indefinite" begin="1.0s" />
</circle>
</g>
</svg>
</body>
</html>示例2:CSS 动画与 SVG
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS 动画与 SVG</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; }
/* CSS 动画 */
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes pulse {
0%, 100% { r: 25; opacity: 0.8; }
50% { r: 35; opacity: 0.5; }
}
@keyframes dash {
to { stroke-dashoffset: 0; }
}
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes colorCycle {
0% { fill: #e94560; }
25% { fill: #f8b500; }
50% { fill: #3fb950; }
75% { fill: #58a6ff; }
100% { fill: #e94560; }
}
.css-rotate {
animation: rotate 4s linear infinite;
transform-origin: center;
}
.css-pulse {
animation: pulse 2s ease-in-out infinite;
}
.css-dash {
stroke-dasharray: 500;
stroke-dashoffset: 500;
animation: dash 3s linear infinite;
}
.css-color {
animation: colorCycle 4s linear infinite;
}
.css-fade {
animation: fadeInUp 1s ease-out forwards;
}
/* hover 效果 */
.hover-scale {
transition: transform 0.3s ease;
cursor: pointer;
}
.hover-scale:hover {
transform: scale(1.2);
}
</style>
</head>
<body>
<h1>CSS 动画与 SVG</h1>
<svg width="700" height="350" viewBox="0 0 700 350">
<!-- CSS 旋转 -->
<text x="100" y="25" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">CSS 旋转</text>
<g class="css-rotate" style="transform-origin: 100px 100px;">
<rect x="70" y="70" width="60" height="60" rx="8" fill="#58a6ff" />
</g>
<!-- CSS 脉冲 -->
<text x="250" y="25" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">CSS 脉冲</text>
<circle cx="250" cy="100" class="css-pulse" fill="#e94560" />
<!-- CSS 描边动画 -->
<text x="450" y="25" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">CSS 描边动画</text>
<text x="450" y="110" text-anchor="middle" font-size="48" font-weight="bold"
fill="none" stroke="#3fb950" stroke-width="2" class="css-dash">
STROKE
</text>
<!-- CSS 颜色循环 -->
<text x="620" y="25" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">CSS 颜色</text>
<circle cx="620" cy="100" r="30" class="css-color" />
<!-- Hover 效果 -->
<text x="350" y="175" text-anchor="middle" font-size="12" fill="#58a6ff" font-weight="bold">Hover 交互效果</text>
<g class="hover-scale" style="transform-origin: 150px 240px;">
<rect x="115" y="205" width="70" height="70" rx="10" fill="#e94560" />
</g>
<g class="hover-scale" style="transform-origin: 280px 240px;">
<circle cx="280" cy="240" r="35" fill="#3fb950" />
</g>
<g class="hover-scale" style="transform-origin: 420px 240px;">
<polygon points="420,205 455,275 385,275" fill="#f8b500" />
</g>
<g class="hover-scale" style="transform-origin: 560px 240px;">
<rect x="525" y="205" width="70" height="70" rx="35" fill="#d2a8ff" />
</g>
<!-- 提示 -->
<text x="350" y="320" text-anchor="middle" font-size="11" fill="#8b949e">鼠标悬停上方图形查看缩放效果</text>
</svg>
</body>
</html>五、浏览器兼容性
提示:Edge 和 IE 不支持 SMIL 动画,可使用 CSS 动画或 JavaScript 作为替代方案。
六、注意事项与最佳实践
1. SMIL vs CSS 选择
-
需要兼容 IE/Edge:使用 CSS 动画
-
需要 animateMotion:使用 SMIL
-
简单属性动画:CSS 更简洁
-
复杂交互:JavaScript 更灵活
2. CSS transform-origin
代码示例
/* SVG 元素的 transform-origin 默认是 SVG 画布原点 */
/* 需要显式设置 */
.css-rotate {
transform-origin: 100px 100px; /* 使用像素值 */
/* 或 */
transform-box: fill-box;
transform-origin: center;
}3. 动画性能
-
优先动画
transform和opacity属性 -
避免动画
width、height、x、y等触发布局重排的属性 -
使用
will-change: transform提示浏览器优化
4. SMIL 动画的 additive 属性
代码示例
<!-- additive="sum" 让动画值叠加而非替换 -->
<rect x="50" y="50" width="50" height="50">
<animateTransform attributeName="transform" type="scale"
values="1;1.2;1" dur="2s" repeatCount="indefinite" additive="sum" />
</rect>七、代码规范示例
代码示例
<!-- 推荐:SMIL 动画规范 -->
<circle cx="100" cy="100" r="25" fill="#58a6ff">
<!-- 属性名、值、时长、重复次数清晰标注 -->
<animate
attributeName="r"
values="25;35;25"
dur="2s"
repeatCount="indefinite"
calcMode="spline"
keyTimes="0;0.5;1"
keySplines="0.4 0 0.6 1;0.4 0 0.6 1" />
</circle>
<!-- 推荐:CSS 动画规范 -->
<style>
@keyframes svg-pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.2); }
}
.animated-element {
animation: svg-pulse 2s ease-in-out infinite;
transform-box: fill-box;
transform-origin: center;
}
</style>八、常见问题与解决方案
常见问题
SMIL 动画在 Edge/IE 不工作?
解决方案:使用 CSS 动画替代,或使用 polyfill 库如 svg4everybody。
CSS transform 在 SVG 中行为异常?
解决方案:设置 transform-box: fill-box 和 transform-origin: center。
如何暂停 SMIL 动画?
使用 JavaScript 控制:anim.pauseAnimation() 暂停,anim.resumeAnimation() 恢复。
描边动画如何实现?
通过 stroke-dasharray 和 stroke-dashoffset 配合 animate 实现描边绘制效果。
九、总结
SVG 动画提供了丰富的视觉表现力,关键要点:
-
SMIL animate:属性动画,支持关键帧和缓动
-
SMIL animateTransform:变换动画(平移、旋转、缩放)
-
SMIL animateMotion:沿路径运动
-
CSS animation:兼容性好,适合简单动画
-
CSS transition:交互式过渡效果
-
兼容性:SMIL 不支持 IE/Edge,CSS 动画兼容性更好
-
性能:优先动画 transform 和 opacity
-
描边动画:通过 stroke-dasharray/dashoffset 实现
下一教程将介绍 SVG 剪辑与遮罩。
本文涉及AI创作
内容由AI创作,请仔细甄别