mcpField
C
css-animations

css-animations

github.com/chanjing-ai创意与媒体0182 次安装14 周前更新
代码仓库

关于 css-animations

面向 FrameVideo 的 CSS 动画技能,可在视频合成中定位关键帧状态。适用于装饰效果和简单的有限动画;需要精确编排多个元素时则使用 GSAP。

主要功能

  1. 01定位 CSS 关键帧动画
  2. 02制作有限循环装饰效果
  3. 03添加独立元素入场动画
  4. 04与 GSAP 配合使用
  5. 05检查时序与渲染

适用场景

  1. 01为合成添加微光或辉光
  2. 02制作徽标脉冲动画
  3. 03创建元素独立入场效果

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/chanjing-ai/framevideo --skill css-animations

安装后在 Claude Code 中输入/css-animations确认已加载。

详细介绍

FrameVideo 的 CSS 动画

FrameVideo 可以通过其 css 运行时适配器为 CSS 关键帧动画定位。可将其用于简单的重复图案、背景动效、闪烁、发光、遮罩和非序列化装饰。

对于场景编排,GSAP 通常更清晰。CSS 动画最适合应用于动效只涉及单个元素且时长固定的情况。

何时使用

在以下情况下使用 CSS 动画:

  • 装饰层 — 背景图案、闪烁效果、颗粒、无需精确计时的细微视差
  • 简单循环 — 重复次数已知的脉冲、发光、呼吸效果
  • 单元素动效 — 每个元素独立播放的入场动画
  • 零依赖动效 — 希望实现动画但无需加载 GSAP 或其他库时
  • GPU 加速效果 — 浏览器会自动优化的变换和不透明度动画

不要使用

以下情况应避免使用 CSS 动画:

  • 场景编排 — 需要精确计时的多元素序列 → 使用 gsap
  • 复杂时间线 — 任何需要暂停/恢复控制或动态时长的内容 → 使用 gsap
  • 无限循环 — 除非已确认浏览器会公开可定位的 WAAPI 句柄(在无头渲染中很少见)
  • 交互式动画 — 悬停、滚动或用户触发的动效无法确定性地渲染
  • 布局动画 — 为 top、left、width、height 设置动画会导致重排 → 改用变换

约定

  • 在运行时初始化完成前,将动画元素放入 DOM。
  • 为定时元素设置 data-start 值,使局部动画时间与片段时间一致。
  • 使用有限的 animation-duration 和 animation-iteration-count,因为在没有 WAAPI 支持的 CSS 动画的环境中,负延迟回退方案无法表示无界时长。
  • 优先使用 animation-fill-mode: both,使定位后的状态在活动动效开始前和结束后保持不变。
  • 避免使用墙上时钟 JavaScript、悬停触发的状态,以及依赖用户事件的类切换。

适配器会查找计算样式中具有 animation-name 的元素,在可用时定位其浏览器 Animation 句柄,否则会通过负 animation-delay 暂停动画。

基本模式

<div
  id="pulse-ring"
  class="clip pulse-ring"
  data-start="0"
  data-duration="4"
  data-track-index="2"
></div>

<style>
  .pulse-ring {
    width: 280px;
    height: 280px;
    border: 4px solid rgba(255, 255, 255, 0.7);
    border-radius: 50%;
    animation-name: pulse-ring;
    animation-duration: 1200ms;
    animation-timing-function: cubic-bezier(0.2, 0, 0, 1);
    animation-iteration-count: 3;
    animation-fill-mode: both;
  }

  @keyframes pulse-ring {
    from {
      opacity: 0;
      transform: scale(0.82);
    }
    35% {
      opacity: 1;
    }
    to {
      opacity: 0;
      transform: scale(1.18);
    }
  }
</style>

交错模式

使用 CSS 自定义属性,避免重复定义关键帧:

<div class="clip dots" data-start="1" data-duration="3" data-track-index="3">
  <span style="--i: 0"></span>
  <span style="--i: 1"></span>
  <span style="--i: 2"></span>
</div>

<style>
  .dots span {
    display: inline-block;
    width: 18px;
    height: 18px;
    margin-right: 10px;
    border-radius: 50%;
    background: currentColor;
    animation: dot-pop 900ms ease-out both;
    animation-delay: calc(var(--i) * 120ms);
  }

  @keyframes dot-pop {
    from {
      opacity: 0;
      transform: translateY(18px) scale(0.75);
    }
    to {
      opacity: 1;
      transform: translateY(0) scale(1);
    }
  }
</style>

适用场景

  • 重复次数已知的装饰性循环。
  • 遮罩、发光、闪烁、颗粒和细微视差层。
  • 简单的单元素入场动画,无需使用完整的 JS 时间线。

与 GSAP 结合使用

CSS 动画和 GSAP 时间线可以在同一合成中共存。两者的分工如下:

CSS 负责装饰效果:

  • 背景图案、颗粒、噪点
  • 环境光晕、闪烁、脉冲效果
  • 遮罩显现、暗角
  • 细微的环境动效(浮动粒子、缓慢漂移)

GSAP 负责场景编排:

  • 字幕计时和排序
  • 场景过渡和交叉淡化
  • 与音频协调的 UI 元素入场
  • 可精确控制的多元素交错动画
同步模式

CSS 动画计时与片段的 data-start 对齐:

<div class="clip bg-shimmer" data-start="0" data-duration="10">
  
</div>

<script>
  const tl = gsap.timeline();
  tl.to("#caption-1", { opacity: 1, duration: 0.5 }, 2);
  tl.to("#caption-2", { opacity: 1, duration: 0.5 }, 5);
  // GSAP controls captions, CSS handles background
</script>

CSS 适配器和 GSAP 适配器独立运行,但两者都会遵循 FrameVideo 的全局时间线,因此在预览和渲染时能保持同步。

高级模式

使用自定义属性实现复杂交错

对于基于数据属性或计算值实现的交错动画:

<div class="grid">
  <div class="cell" style="--row: 0; --col: 0"></div>
  <div class="cell" style="--row: 0; --col: 1"></div>
  
</div>

<style>
  .cell {
    animation: cell-reveal 600ms ease-out both;
    animation-delay: calc((var(--row) * 3 + var(--col)) * 80ms);
  }

  @keyframes cell-reveal {
    from { opacity: 0; transform: scale(0.8); }
    to { opacity: 1; transform: scale(1); }
  }
</style>
用有限循环实现无限图案

当图案看起来是无限循环,但渲染时必须设置有限循环次数时:

.background-drift {
  /* Appears infinite but is actually 50 iterations over 100s */
  animation: drift 2000ms linear 50;
}

@keyframes drift {
  from { transform: translateX(0); }
  to { transform: translateX(-100px); }
}

规则: 迭代次数 = 片段时长 / 动画时长,向上取整。对于时长为 30s、动画时长为 2s 的片段:animation-iteration-count: 15。

动画链

在一个元素上依次运行多个动画:

.logo {
  animation: 
    fade-in 800ms ease-out 0s both,
    pulse 1200ms ease-in-out 1s 3 both,
    fade-out 800ms ease-in 4.6s both;
}

@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.05); } }
@keyframes fade-out { from { opacity: 1; } to { opacity: 0; } }

延迟会依次累加:淡入在 0s 开始,脉冲在 1s 开始,淡出在 4.6s 开始。

性能优化
.optimized {
  /* Tell browser to promote to GPU layer */
  will-change: transform, opacity;
  
  /* Prefer transform over position */
  animation: slide-in 600ms ease-out both;
}

@keyframes slide-in {
  /* Good: GPU-accelerated */
  from { transform: translateX(-100px); opacity: 0; }
  to { transform: translateX(0); opacity: 1; }
  
  /* Avoid: causes reflow */
  /* from { left: -100px; } to { left: 0; } */
}

尽可能只为 transform 和 opacity 设置动画。避免使用 width、height、top、left、margin、padding。

性能对比

指标CSS 动画GSAPWAAPIAnime.js
包体积0 KB45 KB0 KB17 KB
初始化时间0 ms8 ms0 ms4 ms
跳转性能⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
GPU 加速自动手动自动手动
最适用于装饰效果序列编排轻量场景精简场景

CSS 更快的情况:

  • 简单循环(脉冲、发光、旋转)
  • 仅使用 GPU 加速属性(transform、opacity)
  • 无需时间轴控制

GSAP 更快的情况:

  • 包含 10+ 个补间动画的复杂序列
  • 精确控制时间和标签
  • 动态设置时长或播放速度
  • 嵌套时间轴

避免

  • 避免使用无限 CSS 动画,除非已确认浏览器会公开可跳转的、由 WAAPI 支持的 CSS 动画句柄。优先使用足以覆盖可见时长的有限迭代次数。
  • 当 transform 可实现效果时,避免对 top、left、width 或 height 等布局属性设置动画。
  • 避免依赖悬停、焦点、滚动或媒体查询来触发渲染关键动画。
  • 启动后避免更改动画类,除非有其他确定性的时间轴控制此更改。

验证

编辑 CSS 动画组合后:

npx framevideo lint      # Check timing contract
npx framevideo validate  # Check runtime errors

手动检查:

  1. 跳转测试 — 拖动预览时间轴,确认动画在每一帧都能保持
  2. 迭代次数 — 确认 animation-iteration-count 覆盖片段时长(结尾没有空白帧)
  3. 填充模式 — 确认设置了 animation-fill-mode: both,使跳转后的状态在前后保持
  4. GPU 图层 — 打开 DevTools Performance,录制渲染过程,确认没有布局抖动

实际示例

示例 1:背景微光

使用场景: 无需加载动画库,为产品卡片背景添加细微的微光效果。

<div class="clip product-card" data-start="0" data-duration="5">
  <div class="shimmer-layer"></div>
  <h2>Product Name</h2>
</div>

<style>
  .shimmer-layer {
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
    animation: shimmer 2s linear infinite;
  }
  @keyframes shimmer {
    from { transform: translateX(-100%); }
    to { transform: translateX(100%); }
  }
</style>

结果: 流畅的微光效果,额外开销为 0 KB,并由 GPU 加速。

示例 2:加载圆点

使用场景: 在组合构建阶段显示动画加载指示器。

<div class="dots">
  <span style="--i: 0"></span>
  <span style="--i: 1"></span>
  <span style="--i: 2"></span>
</div>

<style>
  .dots span {
    animation: dot-bounce 1.4s ease-in-out infinite both;
    animation-delay: calc(var(--i) * 160ms);
  }
  @keyframes dot-bounce {
    0%, 80%, 100% { transform: scale(0); }
    40% { transform: scale(1); }
  }
</style>

结果: 仅使用 CSS 实现经典的三圆点错峰动画。

示例 3:Logo 脉冲环

使用场景: 通过脉冲环效果吸引用户注意 Logo。

<div class="clip logo-intro" data-start="0" data-duration="4">
  <div class="logo-container">
    <img src="logo.svg" alt="Logo">
    <div class="pulse-ring"></div>
  </div>
</div>

<style>
  .pulse-ring {
    position: absolute;
    inset: -20px;
    border: 3px solid rgba(255,255,255,0.6);
    border-radius: 50%;
    animation: pulse 1.5s cubic-bezier(0.2, 0, 0, 1) 2 both;
  }
  @keyframes pulse {
    from { opacity: 0; transform: scale(0.8); }
    35% { opacity: 1; }
    to { opacity: 0; transform: scale(1.2); }
  }
</style>

结果: Logo 周围出现两个扩展环,动画总时长为 3s。

致谢与参考资料

评论

支持 Markdown