Communitygithub.com

白板动画

此技能应用于用户要求“制作白板动画”、“手绘讲解”、“VideoScribe风格”、“手绘解释视频”、“动画化草图绘制过程”、“制作涂鸦/手绘视频”、“展示手绘插图”或“动画化白板上的手写文字”。涵盖 SVG 笔画绘制、跟随路径尖端的手持画笔、错开显示、擦除/划除过渡以及带旁白的导出。

白板动画 是什么?

此白板动画技能专为需要创建“VideoScribe”或“Doodly”风格手绘解释视频的场景而设计。其核心技术是模拟一支手持画笔在画板上逐笔绘制插图和手写文字,同时配合旁白解说。该技能通过动画化 SVG 路径的 `stroke-dashoffset` 属性来实现“路径自绘”效果,并利用 `getPointAtLength` 方法精准定位一支标记手(Marker Hand)的笔尖,使其始终紧贴正在绘制的线条尖端,从而产生逼真的手绘视觉效果。 此技能支持多种动画平台和工作流,包括用于快速 Web 演示的纯 HTML 单文件,以及用于生成最终逐帧确定 MP4/GIF 视频的 Remotion 组合。它提供了完整的动画编排逻辑,包括按旁白顺序错开显示多个元素、在笔画之间抬笔移动、以及通过擦除或反向绘制进行场景过渡。此外,它还包括一个用于精确截图的“?t=N”时间轴调试工具和一个详细的验证清单,确保手部动画与笔画绘制完美同步,从而生成高质量、无瑕疵的白板动画。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/playlikeboy/videos-skill/tree/HEAD/.claude/skills/whiteboard-animation

在你喜欢的 AI 中提问

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

文档

白板动画 是做什么的?

VideoScribe / Doodly 风格:一只手在画板上逐笔绘制插图和手写文字,同时伴有旁白解说。通过动画化 SVG 路径实现“路径自绘”,并让一个标记手跟随绘制尖端,然后按旁白顺序排列元素,使画板逐步填满。

何时使用

  • “手绘”/涂鸦讲解视频:一只手在白板上绘制艺术图形和文字。
  • 动画化草图或 Logo 的实时逐线绘制过程。
  • 手写文字按照书写顺序出现,并与配音同步。
  • 将静态插图转换为引导性的、逐笔揭示的动画。

核心机制:SVG 笔画绘制

通过将 stroke-dashoffset 从全长动画到 0,路径会“自行绘制”——虚线间隙缩小,从起点到终点逐步暴露笔画。

const path = document.querySelector("#stroke");
const len  = path.getTotalLength();
path.style.strokeDasharray  = len;       // 一个与整个路径等长的虚线
path.style.strokeDashoffset = len;       // 完全推出视图 = 不可见
path.getBoundingClientRect();            // 强制重排后再过渡
path.style.transition       = "stroke-dashoffset 1.2s linear";
path.style.strokeDashoffset = "0";       // 从起点绘制到终点

在 <path> 上使用 pathLength="1" 进行归一化:这样 stroke-dasharray:1; stroke-dashoffset:1 可以绘制任何实际长度的路径,并且一个简单的缓动值 (0→1) 就代表了绘制进度。使用 linear(或极其平缓的缓动)会让绘制看起来像稳定的手笔;在长笔画上避免使用 ease-in-out——它会使标记手产生顿挫感。

标记手跟随尖端

此效果的成败关键在于标记手是否精确地位于正在绘制的点位上。在每一帧采样当前绘制进度下的路径点,并将手部图像放置在该位置;手部素材的笔尖必须与路径点对齐(偏移图像,使其笔尖,而非其角落,落在点上)。

const hand = document.querySelector("#hand");   // <img>/<g>,笔尖在其左上角"笔头"处
const NIB = { x: 6, y: 4 };                      // 手部图像内的笔尖偏移量
function drawOn(path, hand, dur = 1200) {
  const len = path.getTotalLength(), t0 = performance.now();
  path.style.strokeDasharray = len;
  (function frame(now) {
    const k = Math.min(1, (now - t0) / dur);     // 0→1 的进度
    path.style.strokeDashoffset = len * (1 - k); // 暴露起点到尖端
    const p = path.getPointAtLength(len * k);    // SVG 坐标中的当前尖端位置
    hand.setAttribute("transform", `translate(${p.x - NIB.x} ${p.y - NIB.y})`);
    if (k < 1) requestAnimationFrame(frame);
  })(t0);
}

getPointAtLength(len * k) 是核心:它返回的路径坐标与驱动 strokeDashoffset 的进度相同,因此笔尖始终紧贴正在增长的笔画。在不同笔画之间需要抬起手(淡出,跳转到下一个起点),以免它在空白画板上滑动。

显示顺序——画板逐步填充

按照人们绘制场景的方式,以旁白顺序排列元素:每个插图和每个手写文字块依次绘制、保持,然后下一个开始。在一个图形内部错开笔画;每个元素完成后稍作停顿再移动手。一个图形对应一段旁白节拍。不要同时绘制两样东西——眼睛(以及单只手)一次只能跟随一个尖端。

步骤机制
绘制一条笔画stroke-dashoffset 从 len 到 0,手位于 getPointAtLength(len*k)
多笔画图形错开笔画;手跳到每个新笔画的起点
手写文字按阅读顺序绘制每字母/单词的笔画,手跟随
保持元素完成绘制后,手在画面外暂停 (0.4–1.0 秒)
下一个元素移动/淡入手到下一个起点;开始其绘制
擦除 / 清除划除或反向绘制以清空画板,为下一部分做准备

将艺术作品转换为可绘制的路径

绘制动画需要单笔画、开放的、按绘制顺序排列的路径——而不是填充的复合形状。

  • 创作或描摹线条艺术时使用开放笔画(Illustrator/Inkscape:轮廓线,而非填充)。填充的色块没有可动画化的“笔画”;应将填充转换为中心线笔画,或在轮廓完成后填充轮廓路径。
  • 顺序很重要:<path> 元素在 SVG 中应按照手绘制的顺序出现——按照它们在文档中的顺序进行动画。
  • 长连续线条看起来最自然;仅在真正需要提笔的地方断开。
  • 对于纯色区域:首先绘制轮廓笔画,然后在其后方淡入/放大填充(使用 opacity 或剪辑揭示),使其看起来像“之后填色”。
  • 手写文字:使用笔画/手写字体,将字形转换为路径,然后按笔画顺序绘制每个字形的路径。或者模拟它:遮罩单词,从左到右扫过一个揭示层,让手位于遮罩边缘。

标记手部素材

一个拿着马克笔的手的 PNG/SVG 图像,笔尖位于已知点。测量一次笔尖偏移量(上面的 NIB)并重复使用。为整个作品保持一个手部素材以确保一致性。仅在需要左手时才镜像它(scaleX(-1))。在手下添加淡淡的阴影以增加深度;在手“离开”的保持期间去掉阴影。

擦除 / 划除过渡

在章节之间,清空画板以免造成混乱:

  • 划除:对已填充的组动画化一个 clip-path(或一个白色矩形)进行划除,手部可选地“擦除”。
  • 反向绘制:运行 strokeDashoffset 从 0 到 len 来反向绘制,手部跟随。
  • 淡出 + 重绘:将旧组淡出,同时开始下一组的绘制。

保持一种清晰的语法(例如,始终从左到右划除),这样过渡就显得有目的性。

与旁白同步节奏

绘制持续时间应跟随口语台词,而不是固定计时器。根据旁白估算,大约每秒 2.3 个词;将每个图形的总绘制时间设定为其所说明的台词长度大致相同,再加上一个短暂的保持。旁白提到的标签应在词语说出时正好完成绘制。对于强调性的台词,减慢手速;对于次要的连接性笔画,加快速度。永远不要让手在绘制的画板上闲置而旁白继续——将手移开或开始下一个元素。

输出清单

  • 每个笔画都是按绘制顺序排列的单个开放路径;没有元素是突然完全出现的。
  • 在整个绘制过程中,标记笔尖精确地位于绘制尖端(无漂浮,无延迟)。
  • 手在不同笔画/元素之间干净地抬起;不在空白画板上滑动。
  • 元素按旁白顺序依次绘制;每个元素在下一个开始前有所保持。
  • 手写文字按阅读顺序绘制;填充在其轮廓之后出现。
  • 擦除/划除语法一致;画板从不过度杂乱。
  • 绘制时间与其所说明的 VO 台词同步。
  • prefers-reduced-motion:显示完成的画板(所有笔画偏移量为 0,手部隐藏),无绘制动画。

交付与验证(独立 HTML)

打包的帮助脚本 (scripts/):scripts/seek-shot.sh anim.html 0 1.5 3 冻结 ?t=N 测试工具并在每个时刻截图;scripts/contact-sheet.sh sheet.png frame-*.png 将它们平铺以便快速审阅。详见 scripts/README.md。

对于一个自包含的白板场景(绘制插图、手写文字、简短的手绘节拍),交付物是一个可直接在浏览器中打开的 HTML 文件——无需构建步骤,无需渲染管道。单个文件非常适合网页动效;当一个文件就能完成工作时,不要使用打包工具。(对于带有内置 VO 的完整解说手绘视频,应将其构建为 Remotion 组合并通过 remotion still 验证——参见 explainer-video。)

输出约定:

  • 一个 .html 文件:内联 SVG(路径按绘制顺序排列,使用 pathLength="1" 或测量长度)、手部素材以数据 URI 内联,以及一个内联 <script> 中的绘制驱动脚本。
  • 所有绘制在一个主时间线上(GSAP tl,或一个 rAF 时钟),因此整个序列具有单个可搜索的播放头——strokeDashoffset 和手部位置都由相同的进度值驱动。
  • 包含下面的搜索工具,以便任何时刻都可被冻结用于截图。在 t 时刻冻结显示了路径绘制的精确程度——验证依赖于此。

搜索工具——冻结精确时刻用于截图。 ?t=N 将主时间线搜索到 N 秒并暂停,以便截图能捕捉到绘制过程中的一个静止、确定的帧。

<script>
  // ... 构建您的主时间线为 `tl`(在其上放置 drawOn 调用)...
  const t = new URLSearchParams(location.search).get("t");
  if (t !== null) { tl.pause(); tl.seek(parseFloat(t)); }  // 冻结在 t 秒
  // 无 ?t → 正常播放
  window.__ready = true;            // 为无头等待准备的就绪信号
  console.log("duration", tl.duration());
</script>

验证循环——渲染→冻结→截图→检查:

  1. 在时间线的各个时刻打开文件——开始、绘制过程中的一帧、结束: …/scribe.html?t=0,?t=<dur/2>,?t=<dur>。从控制台读取 tl.duration() 作为结束时间。选择至少一个处于笔画绘制过程中间的 t——这正是手在尖端上的视觉效果被证明或打破的地方。
  2. 对每个冻结帧进行无头截图:
    npx playwright screenshot --wait-for-timeout=500 "file://$PWD/scribe.html?t=1.2" frame-mid.png
    
  3. 检查每一帧——检查保真度:在笔画中间时刻 t,标记笔尖精确地位于已绘制部分的前沿尖端上(不前,不后,不漂浮);路径仅绘制到尖端;在 ?t=<dur> 时刻,每个笔画都干净地完成,没有间隙,没有过冲,没有剩余的虚线。检查伪影:笔画之间手在空白画板上滑动、笔尖偏移错误(尖端漂浮在线条之上)、笔画绘制顺序错误、填充在其轮廓之前出现、被裁剪/画布外的图形、字体加载前的 FOUC(Flash of Unstyled Content,样式未加载时的闪白)。
  4. 迭代:调整 NIB、笔画顺序、持续时间,并重新截图,直到每个冻结帧看起来都像一只手正在绘制过程中。

在完成之前:

  1. 在浏览器中独立打开——无控制台错误,无缺失的 CDN/资源。
  2. 一个主时间线;?t=N 正确冻结,并且 strokeDashoffset 和手部位置共享一个进度值。
  3. 在开始/绘制过程中间/结束时截图——整个过程中手部笔尖精确地位于尖端上,笔画在结束时干净完成,绘制顺序正确。
  4. 手在笔画之间抬起;不在空白画板上滑动。
  5. prefers-reduced-motion 显示完成的画板(所有笔画已绘制,手部隐藏),无绘制动画。

对于带有旁白、帧确定的导出,将相同的绘制驱动(使用 useCurrentFrame()/fps 驱动 strokeDashoffset 和手部变换)移植到 Remotion 合成中,并渲染为 MP4/GIF——参见 explainer-video 技能中关于渲染静态帧然后编码的循环。

参考文件

  • references/draw-on-recipes.md——可运行的绘制机制:getTotalLength/getPointAtLength 手跟随路径、GSAP DrawSVGPlugin 和 MotionPathPlugin 变体、多笔画错开、每字形手写、轮廓后填充、擦除/划除和反向绘制过渡,以及 Remotion 帧驱动移植。
  • references/whiteboard-pipeline.md——将艺术作品转换为可绘制的单笔画 SVG、绘制顺序创作、手写/笔画字体、标记手部素材和笔尖校准、将绘制时间与 VO 台词同步,以及故事板到画板的构建序列。

Individual skills in this repo

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

animated-infographic

This skill should be used when the user asks to "make an animated infographic", "create an infographic video", "build an infographic animation", "animate an explainer infographic", "do a sequenced reveal of icons and stats", "animate icons with key numbers and connectors", or "lay out a designed infographic that animates in sequence". Covers infographic layout & visual hierarchy, staggered element reveals, animating icons/pictograms, key-number counters, connectors/flow, and section pacing. For heavy charting (bar chart race, charts from a CSV) use the chart-animation skill instead.

brand-motion-guidelines

This skill should be used when the user asks to "write motion guidelines", "create a brand motion system", "define easing and timing tokens", "document our animation principles", "build a motion language like Slack/IBM/Klarna", "set up entrance/exit/transition rules", or "add a reduced-motion / accessibility section". It outputs a fill-in-ready brand motion guidelines document.

explainer-video

This skill should be used when the user asks to "make an explainer video", "turn this into a short explainer", "write a script and storyboard for a product video", "produce a how-it-works/onboarding video", "sync narration and captions", or "build a 30–90s animated explainer". Covers script→storyboard→scene build→narration/caption sync→edit→polish.

presentation-video

This skill should be used when the user asks to "make an animated presentation", "turn a pitch deck into a video", "convert slides/a deck to video", "make a presentation video", "build a deck video", "narrate a slide deck as a video", or "auto-advance slides synced to a voiceover". Covers rebuilding slides as motion graphics with staggered build reveals, slide-to-slide transitions, and timing locked to per-slide narration.

product-demo-video

This skill should be used when the user asks to "make a product demo video", "create an app demo video", "build a feature announcement video", "do a SaaS demo", "make a UI walkthrough video", "animate product screenshots into a demo", "add an animated cursor/click to a screenshot", or "zoom into part of a UI". Covers turning static screenshots/designs (not screen recordings) into a clean animated demo: device/browser frames, animated cursor + click ripple, zoom/pan to focal UI, callout annotations, step pacing, screen-to-screen transitions, and feature captions.

shot-composition

This skill should be used when the user asks to "compose a frame", "set up a grid", "plan shot composition", "place the focal point", "decide where elements enter and exit", "add a parallax/camera move", "adapt a layout for 16:9 / 9:16 / 1:1", or "keep content inside safe areas". Covers grids, safe areas, focal hierarchy, and 2D/3D camera framing.

相关技能