mcpField
W
whiteboard-animation

whiteboard-animation

github.com/iart-ai创意与媒体601.5k 次安装18 周前更新
代码仓库

关于 whiteboard-animation

whiteboard-animation 是利用 SVG 路径制作手绘白板动画的技能,适合创作讲解内容的制作者。它涵盖逐笔绘制、笔尖跟随、按旁白编排元素,以及独立 HTML 或 Remotion 视频输出。

主要功能

  1. 01SVG 路径逐笔绘制
  2. 02手持笔尖跟随绘制位置
  3. 03按旁白顺序编排场景
  4. 04手写动画与画板清除转场
  5. 05输出独立 HTML 或 Remotion 视频

适用场景

  1. 01制作白板手绘解说视频
  2. 02呈现草图或 Logo 的绘制过程
  3. 03让书写标签与旁白同步

安装

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

$npx skills add https://github.com/iart-ai/explainer-video-skills --skill whiteboard-animation

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

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

README.md
references/
draw-on-recipes.md
whiteboard-pipeline.md

详细介绍

白板动画

VideoScribe / Doodly 风格:一只手在白板上逐笔绘制插画和手写文字,同时旁白进行讲解。通过会自行绘制的动画 SVG 路径和跟随绘图笔尖的马克笔手部来实现,然后按旁白顺序排列各个元素,让内容逐步填满白板。

适用场景

  • 制作“手绘讲解”或涂鸦风格的说明视频,让一只手在白板上绘制艺术图案和文字。
  • 动画呈现草图或徽标的实时绘制过程,逐线展现。
  • 制作与配音同步的自动手写效果。
  • 将静态插画转变为逐笔呈现的引导式展示。

核心机制:SVG 描边绘制效果

通过将 stroke-dashoffset 从路径的完整长度动画到 0,让路径“自行绘制”:间隙逐渐缩小,描边便从起点到终点逐渐显现。

const path = document.querySelector("#stroke");
const len  = path.getTotalLength();
path.style.strokeDasharray  = len;       // one dash as long as the whole path
path.style.strokeDashoffset = len;       // pushed fully out of view = invisible
path.getBoundingClientRect();            // force reflow before transitioning
path.style.transition       = "stroke-dashoffset 1.2s linear";
path.style.strokeDashoffset = "0";       // draws start → end

在 <path> 上使用 pathLength="1" 进行归一化:这样,stroke-dasharray:1; stroke-dashoffset:1 就能绘制任意路径,无论其实际长度如何;单个缓动值(0→1)就是绘制进度。使用 linear(或非常轻缓的缓动)会显得运笔平稳;长笔画应避免使用 ease-in-out,否则马克笔会显得一顿一顿。

马克笔手部跟随笔尖

这种效果的成败取决于手部是否准确位于正在绘制的点上。根据当前绘制进度采样路径,并在每一帧将手部图像放到该位置;手部素材的笔尖必须与路径点对齐(调整图像偏移,让笔尖而非图像角落落在该点上)。

const hand = document.querySelector("#hand");   // <img>/<g>, tip at its top-left "nib"
const NIB = { x: 6, y: 4 };                      // nib offset inside the hand art
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 progress
    path.style.strokeDashoffset = len * (1 - k); // expose start→tip
    const p = path.getPointAtLength(len * k);    // current tip in SVG coords
    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.0s)
下一个元素将手部移至下一个起点或淡出后再移入;开始绘制该元素
擦除 / 清除擦除或反向绘制,清空白板以展示下一部分

将图稿转换为可绘制路径

绘制效果需要按绘制顺序排列的单笔开放路径,而不是填充的复合形状。

  • 将线稿制作或描摹为开放笔画(在 Illustrator/Inkscape 中使用轮廓,而非填充)。填充的色块没有可供动画呈现的“描边”;请将填充转换为中心线描边,或绘制轮廓路径,并在轮廓绘制完成后再填充。
  • 顺序很重要:<path> 元素应在 SVG 中按照手部的绘制顺序排列,并按文档顺序为它们制作动画。
  • 连续的长线条看起来最自然;只在现实中需要抬笔的地方断开。
  • 对于纯色区域:先绘制轮廓描边,再在其后淡入或渐显填充(使用 opacity 或裁剪揭示),这样看起来才像是“描完轮廓后再填色”。
  • 手写文字:使用描边字体或手写字体,将字形转换为路径,然后按笔画顺序绘制每个字形的路径。也可以模拟:遮罩文字并从左向右扫动显现,同时让手部沿着遮罩边缘移动。

马克笔手部素材

使用一张手握马克笔的 PNG/SVG 图片,并确定笔尖的位置。只需测量一次笔尖偏移量(上文的 NIB),之后重复使用。整部作品使用同一手部素材,以保持一致。只有在需要左手时才将其镜像(scaleX(-1))。在手部下方添加淡淡的阴影以增加立体感;停留时手部“离开”画板,应隐藏阴影。

擦除/擦除转场

在不同章节之间清空画板,避免内容堆得太满:

  • 擦除:让 clip-path(或白色矩形)横向扫过已填充的组,将其擦除;可选地让手做出「擦除」动作。
  • 反向绘制:将 strokeDashoffset 从 0→len 播放,让笔迹逐渐消失,手向后跟随。
  • 淡出并重绘:让旧组淡出,同时开始绘制下一组。

保持统一的规则(例如始终从左向右擦除),让转场显得有意为之。

与旁白同步节奏

绘制时长应与口播时长同步,而不是使用固定计时器。按 VO 每秒约 2.3 个单词估算;每次绘制的总时长应大致等于所对应台词的时长,再加上短暂的停留。VO 说出某个标签时,该标签应恰好绘制完成。强调性台词时放慢手的速度;次要的衔接笔画则加快。旁白继续时,不要让手停在已绘制完成的画板上——让它移开,或开始绘制下一个元素。

输出检查清单

  • 每条笔画都是按绘制顺序绘制的单一开放路径;不要让任何内容以完整形态突然出现。
  • 每条笔画绘制期间,手的笔尖都要精准停在绘制前端(不得悬空或滞后)。
  • 不同笔画/元素之间,手要干净地抬起;不要在空白画板上滑动。
  • 按旁白顺序逐个绘制元素;每个元素绘制完成后都要停留一段时间,再绘制下一个。
  • 手写内容按阅读顺序绘制;填充效果在轮廓完成后出现。
  • 擦除规则保持一致;不要让画板内容过于拥挤。
  • 绘制时长与所对应的 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" 或测量路径长度)、内嵌手部素材或将其设为 data-URI,并在一个内联 <script> 中放入绘制动画驱动代码。
  • 所有绘制都在同一个主时间轴上(GSAP tl,或单个 rAF 时钟),这样整个序列只有一个可跳转的播放头——strokeDashoffset 和手部位置都由同一个进度值驱动。
  • 加入下方的跳转测试框架,以便将任意时刻冻结并截图。冻结在 t 时会显示路径实际绘制到的程度——验证依赖于此。

跳转测试框架——冻结精确时刻以便截图。 ?t=N 会将主时间轴跳转到 N 秒并暂停,因此截图会得到一帧静止且确定的中途绘制画面。

<script>
  // ... build your master timeline as `tl` (drawOn calls placed on it) ...
  const t = new URLSearchParams(location.search).get("t");
  if (t !== null) { tl.pause(); tl.seek(parseFloat(t)); }  // frozen at t seconds
  // no ?t → plays normally
  window.__ready = true;            // ready signal for headless wait
  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。
  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 台词调整绘制时长,以及从分镜到白板的构建流程。

评论

支持 Markdown