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

多媒体:SVG动画 - 完整教程与代码示例

一、教程简介

SVG 提供了多种动画实现方式:SMIL 动画(<animate><animateTransform> 等)、CSS 动画和 JavaScript 动画。SMIL 是 SVG 原生的动画机制,无需 JavaScript 即可实现属性动画和变换动画。CSS 动画则利用 CSS 的 transition 和 animation 属性。本教程将详细讲解 SVG 动画的各种实现方法。


二、核心概念

动画方式对比

方式 说明 优点 缺点
SMIL SVG 原生动画 声明式、无需 JS IE 不支持
CSS CSS transition/animation 兼容性好 仅限 CSS 属性
JavaScript requestAnimationFrame 完全控制 代码量大

SMIL 动画元素

元素 说明
<animate> 属性动画
<animateTransform> 变换动画(平移、旋转、缩放)
<animateMotion> 沿路径运动
<set> 设置属性值(无过渡)

三、语法与用法

animate - 属性动画

代码示例

<circle cx="50" cy="50" r="20" fill="#58a6ff">
  <animate attributeName="r" from="20" to="40" dur="2s" repeatCount="indefinite" />
</circle>
属性 说明
attributeName 要动画的属性名
from/to 起始/结束值
values 关键帧值列表
dur 动画时长
repeatCount 重复次数(indefinite=无限)
fill 动画结束状态(freeze=保持)
begin 开始时间/条件
calcMode 计算模式(linear/discrete/spline)
keyTimes 关键帧时间点
keySplines 贝塞尔缓动曲线

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 类型:translaterotatescaleskewXskewY

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>

五、浏览器兼容性

动画方式 Chrome Firefox Safari Edge IE
SMIL animate 2+ 4+ 3+ 不支持 不支持
SMIL animateTransform 2+ 4+ 3+ 不支持 不支持
SMIL animateMotion 2+ 4+ 3+ 不支持 不支持
CSS animation 4+ 5+ 6+ 12+ 10+
CSS transition 4+ 4+ 6+ 12+ 10+

提示: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. 动画性能

  • 优先动画 transformopacity 属性

  • 避免动画 widthheightxy 等触发布局重排的属性

  • 使用 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-boxtransform-origin: center

如何暂停 SMIL 动画?

使用 JavaScript 控制:anim.pauseAnimation() 暂停,anim.resumeAnimation() 恢复。

描边动画如何实现?

通过 stroke-dasharraystroke-dashoffset 配合 animate 实现描边绘制效果。


九、总结

SVG 动画提供了丰富的视觉表现力,关键要点:

  • SMIL animate:属性动画,支持关键帧和缓动

  • SMIL animateTransform:变换动画(平移、旋转、缩放)

  • SMIL animateMotion:沿路径运动

  • CSS animation:兼容性好,适合简单动画

  • CSS transition:交互式过渡效果

  • 兼容性:SMIL 不支持 IE/Edge,CSS 动画兼容性更好

  • 性能:优先动画 transform 和 opacity

  • 描边动画:通过 stroke-dasharray/dashoffset 实现

下一教程将介绍 SVG 剪辑与遮罩。

标签: SVG动画 SMIL动画 CSS动画 路径运动 SVG教程 描边动画

本文涉及AI创作

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

list快速访问

上一篇: 多媒体:SVG滤镜 - 完整教程与代码示例 下一篇: 多媒体:剪辑与遮罩 - 完整教程与代码示例

poll相关推荐