Communitygithub.com

og-image-animated

将项目的 Open Graph 分享卡片转换为几秒钟的网页动画——品牌标识和标题从顶部落下,真实应用窗口从底部升起并最终稳定到静态卡片上。在项目技术栈中创建一个可播放的路由,并按帧录制为 MP4 和 GIF(以及最终帧的 PNG)。

og-image-animated 是什么?

og-image-animated 是一个 AI 代理技能,用于为项目的 Open Graph 分享卡片添加简短、流畅的动画效果。它基于组件的现有标记和布局,通过纯 CSS 动画(opacity 和 transform: translateY)实现品牌标识和标题从顶部淡入下滑、应用窗口从底部淡入上升的流畅揭示效果。该技能支持在项目技术栈中创建一个可预览的网页路由,并自动使用 Headless 浏览器(Playwright)逐帧录制动画,输出 MP4、GIF 和最终帧 PNG 文件。它适用于 Claude Code、Cursor 等支持自定义技能的开发环境,确保动画与静态卡片保持同步,避免内容漂移。输出文件可用于社交媒体帖子、README 或启动页面,但建议保留静态 PNG 作为 og:image,因为社交平台不支持动画 OG 图像。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/paralect/saas-skills/tree/HEAD/skills/og-image-animated

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

动画 OG 图像

此技能使用的所有文件都位于 SKILL.md 旁边的专用文件夹内,路径均相对于该文件夹。它不需要其他技能或其他文件夹中的任何内容,因此无需寻找。除非用户指定了其他位置,否则将生成的所有内容保存在当前项目的 out/og-image-animated/ 目录下。

将静态分享卡片制作为短小而平静的揭示动画:

  1. 空白卡片:仅显示背景和柔和发光。
  2. 品牌标识和标题从顶部落下(淡入 + 下滑)。
  3. 应用窗口从底部升起(淡入 + 上滑)并精确稳定在静态卡片上的位置。
  4. 在最终帧上保持,该帧必须与静态 OG 图像一致。

示例:references/pulse.gif(结果)和 references/pulse-frames.png(四帧:开始、标题进入、应用升起、最终)。

规则

  • 从静态卡片开始。 如果项目还没有 OG 卡片组件,请先按照 references/static-card.md 构建(真实产品、来自当前站点的消息、真实数据)。动画仅添加运动:相同的标记、相同的最终布局,无新内容。
  • 一个组件,两种模式。 向现有卡片组件添加 animated prop,而不是复制它,以便静态 PNG 和动画永不脱离。如果没有该 prop,则不进行动画。
  • 运动,而非特效。 仅使用 opacity + transform: translateY,一个共享的缓出曲线(cubic-bezier(0.16, 1, 0.3, 1))。无弹跳、模糊、缩放弹出、打字机文本或旋转元素。
  • 简短。 整个时间线约 2–2.5 秒,然后保持约 1.5 秒。标题必须在约 1.3 秒时完全可读。
  • 仅使用 CSS 动画(关键帧 + 带有 both fill 的 animation),卡片内无 JS 驱动的补间或计时器。记录器通过 Web Animations API 寻找 CSS 动画;JS 驱动的运动无法确定性地捕获。

时间线

元素关键帧持续时间延迟
品牌标识从 opacity: 0; translateY(-48px) 开始900ms100ms
标题从 opacity: 0; translateY(-48px) 开始1000ms250ms
应用窗口从 opacity: 0; translateY(320px) 开始1300ms700ms

调整距离以适配卡片:应用窗口应从底部边缘下方(约卡片高度的一半)开始,标题则应在其静止位置上方约自身高度处开始。如果有浮动面板,让它最后到达(在窗口开始后 +200ms)。

步骤

1. 发现

  • 找到静态卡片组件及其渲染路由(例如 og-image.tsx、/og/<page>),以及 public/ 中的当前 PNG。
  • 注意品牌标识、标题和应用窗口的包装器。如果窗口使用 zoom 来适配,则对内部包装器进行动画处理,而不是缩放的元素,以保持偏移正确。

2. 添加动画模式

在卡片组件中:

const KEYFRAMES = `
@keyframes og-drop { from { opacity: 0; transform: translateY(-48px); } to { opacity: 1; transform: none; } }
@keyframes og-rise { from { opacity: 0; transform: translateY(320px); } to { opacity: 1; transform: none; } }
`;
const EASE = 'cubic-bezier(0.16, 1, 0.3, 1)';
const enter = (name: string, ms: number, delay: number) => ({ animation: `${name} ${ms}ms ${EASE} ${delay}ms both` });

// <div data-og-frame …>{animated && <style>{KEYFRAMES}</style>} …
// brand:  style={animated ? enter('og-drop', 900, 100) : undefined}
// title:  style={animated ? enter('og-drop', 1000, 250) : undefined}
// window: <div style={{ zoom }}><div className="h-full" style={animated ? enter('og-rise', 1300, 700) : undefined}>…

将关键帧放在组件中(<style> 标签)或项目的全局 CSS 中;使用 Tailwind v4 时,@theme 内的关键帧仅在匹配的 --animate-* token 被使用时才会发出,因此优先使用组件或普通 CSS。

3. 添加一个播放动画的网页路由

作为静态路由的兄弟路由,例如 /og/<page>-animated(noindex,无应用 chrome):

  • 在 1200×630 的框架内渲染 <Card animated />。
  • 重新播放以预览:使用每约 4.5 秒更改的 key 重新挂载卡片。
  • ?loop=0 一次播放(记录器使用此参数)。先将搜索参数规范化为字符串:像 TanStack 这样的路由器会将 ?loop=0 解析为数字 0,如果检查遗漏,则会在录制期间继续重新挂载卡片。

在浏览器中打开并观看几次。检查进入顺序,确保动画开始前没有闪烁,并且最终状态与静态卡片匹配。

4. 录制 MP4 + GIF

在开发服务器运行时:

node <this skill folder>/scripts/record.mjs \
  --url "http://localhost:<port>/og/<page>-animated?loop=0" \
  --out out/og-image-animated/og-<page>

生成 og-<page>.mp4(2400×1260、H.264、30fps)、og-<page>.gif(1200px 宽、调色板优化、循环)和 og-<page>.png(最终帧)。工作原理:它会暂停页面上的每个动画,读取时间线长度,然后逐帧寻找所有动画并截图 [data-og-frame] 的固定区域。每次运行结果一致,无丢帧。选项:--fps、--hold、--lead、--scale、--formats mp4,gif,png、--selector。

需要 PATH 中有 ffmpeg。Playwright 会在首次运行时安装到此技能的 scripts/ 文件夹中,如果找不到其 Chromium 也会安装。

注意事项:

  • 页面不得强制减少运动。许多全局样式表会缩短 prefers-reduced-motion 下的动画;记录器不会模拟它,如果找不到动画会大声失败。
  • 元素截图会等待“稳定”,这在动画中间永远不会发生。这就是脚本剪辑页面区域的原因。
  • 确保端口确实正在提供此应用的响应(另一个本地服务器可以应答 localhost)。

5. 审查

提取联系表并查看:

ffmpeg -y -loglevel error -i og-<page>.mp4 \
  -vf "select='eq(n\,8)+eq(n\,22)+eq(n\,40)+eq(n\,<last>)',scale=1000:-1,tile=2x2" -frames:v 1 sheet.png
  • 约第 0.25 秒:空白卡片(仅发光),无布局弹出。
  • 约第 0.7 秒:标题进入或接近进入,应用窗口尚未可见。
  • 约第 1.3 秒:应用窗口升起中,标题完全可读。
  • 最后一帧:内容与静态 PNG 一致。

保持 GIF 相对较小(约 3MB 以下)。如果更大,降低 --fps(20–24)或缩短 --hold。

输出

告知用户:

  • 预览路由 URL(循环)以及写入的文件(MP4、GIF、PNG)
  • 重新生成的命令
  • 时间线(移动的元素、持续时间)
  • og:image 必须保持为静态 PNG:社交平台不播放动画 OG 图像。在帖子、README、启动页面或支持的地方使用 MP4/GIF 作为 og:video。

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

相关技能