motion-figure

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Motion figure

动态图表

This skill makes figures that move or respond to input. It has three tiers. Use this skill with Claude, Cursor, Codex, OpenClaw, Hermes, or any agent that reads SKILL.md.
TierWhat it makesWhere it goes
1. Lesson figureDeclarative SMIL animation, or a slider widget that redraws an SVG. Both mount from a ```figure fence.Course lessons
2. Mechanism figureAn HTML panel that shows the named parts of a system. The reader drives one control and reads a computed verdict.Standalone pages, READMEs, essays, the course site outside lessons
3. Dither fieldA WebGL band of ordered dither dots in the paper, accent, and ink colours, with four seeded motions.Page mastheads and section breaks
Tier 1 has the most rules, because the lesson runtime has hard limits. Tiers 2 and 3 have their own reference files.
此 skill 用于创建会移动或响应输入的图表,分为三个层级。可与 Claude、Cursor、Codex、OpenClaw、Hermes,或任何能够读取 SKILL.md 的 Agent 一起使用。
层级生成内容使用位置
1. 课程图示声明式 SMIL 动画,或可重绘 SVG 的 Slider 组件。两者都通过 ```figure fence 挂载。课程章节
2. 机制图示一个 HTML 面板,用于展示系统中已命名的部件。读者操作一个控件,并读取计算得出的结论。独立页面、README、文章、课程站点中章节之外的区域
3. Dither 场使用背景纸张色、强调色和墨色绘制的 WebGL 有序抖动点阵带,包含四种带随机种子的运动效果。页面页眉和章节分隔处
第一层的规则最多,因为课程运行时存在严格的限制。第二层和第三层各自拥有对应的参考文件。

When to use

何时使用

  • A lesson explains a process that changes over time: a token that moves through stages, a queue that fills, a loop that repeats.
  • A lesson explains a formula where one input changes the output: learning rate, temperature, chunk size, batch size.
  • An author writes "animate this figure", "add a slider", or "make the diagram interactive".
  • A page needs a demo where the reader changes one thing and sees what the system does: a cache, a queue, a context window, a router. Use tier 2.
  • A page needs a slow moving header in the course colours. Use tier 3.
  • 课程章节讲解随时间变化的流程:token 在各阶段之间移动、队列逐渐填充、循环不断重复。
  • 课程章节讲解某个输入会改变输出的公式:
    learning rate
    、
    temperature
    、
    chunk size
    、
    batch size
    。
  • 作者希望"animate this figure"、"add a slider"或"make the diagram interactive"。
  • 页面需要一个演示,让读者改变某个参数并观察系统的行为,例如
    cache
    、
    queue
    、
    context window
    或
    router
    。使用第二层。
  • 页面需要使用课程配色的缓慢动态页眉。使用第三层。

When not to use

何时不应使用

  • The idea is a fixed structure with no time axis and no input. Make a static SVG figure. The sibling skill
    blueprint-figure
    covers static figures.
  • The page is a full explainer page with its own state model and machine geometry. The sibling skill
    isometric-explainer
    covers that.
  • You only need palette, fonts, or prose rules. The sibling skill
    course-style
    holds those. This skill copies the parts it needs into
    references/tokens.md
    .
  • 创意是固定结构,既没有时间轴,也没有输入。请制作静态 SVG 图表。同级 skill
    blueprint-figure
    涵盖静态图表。
  • 页面是带有自身状态模型和机器几何结构的完整讲解页面。同级 skill
    isometric-explainer
    涵盖此类内容。
  • 只需要调色板、字体或文案规则。同级 skill
    course-style
    包含这些内容。本 skill 会将所需部分复制到
    references/tokens.md
    。

Method

方法

  1. Write one sentence that names the single change the figure shows. If you need two sentences, make two figures.
  2. Pick the tier. Inside a lesson, use tier 1. For tier 2, read
    references/mechanism-figures.md
    and start from
    templates/mechanism.html
    . For tier 3, read
    references/dither-fields.md
    and copy
    templates/dither.js
    . The steps below are for tier 1. In tier 1, use an animated figure when time is the variable. Use a slider widget when a number is the variable.
  3. Pick a name in kebab case, for example
    request-path
    or
    context-budget
    . Search the registry for that name first. A later module that registers the same name replaces the earlier figure.
  4. Put the code in a module file named
    figures-<topic>.js
    . Wrap it in an IIFE, read
    window.LF
    , and return early if it is missing.
  5. Write a figure function
    function (host, cfg)
    . It appends one
    .lf
    card to
    host
    and can return a dispose function.
  6. Build the card:
    .lf-head
    with an uppercase
    .lf-label
    and a short hint,
    .lf-body
    , and
    .lf-cap
    with the caption.
  7. Use
    viewBox="0 0 520 H"
    for the SVG. Most course figures use an H from 200 to 250. A single bar needs less.
  8. Add a
    <title>
    and a
    <desc>
    with ids that you create once, outside any render function.
  9. For an animated figure, add entries first, then one slow loop. Follow
    references/smil-rules.md
    line by line.
  10. For a slider widget, define
    state._render
    before you call
    LF.slider
    or
    LF.select
    . Then call
    state._render()
    once at the end.
  11. Call
    LF.register({ 'your-name': fn })
    at the end of the module.
  12. In the lesson Markdown, add the fence. Put the name on the first line and optional JSON config after it:
    markdown
    ```figure
    context-budget {"windowK": 32}
    ```
  13. Run the checks in "Check before you finish". Look at the figure in light theme, dark theme, at 375 px width, and with reduced motion on.
  1. 写一句话,说明图表展示的唯一变化。如果需要两句话,请制作两个图表。
  2. 选择层级。在课程内部使用第一层。对于第二层,阅读
    references/mechanism-figures.md
    并以
    templates/mechanism.html
    为起点。对于第三层,阅读
    references/dither-fields.md
    并复制
    templates/dither.js
    。以下步骤适用于第一层。在第一层中,当变量是时间时使用动画图表;当变量是数值时使用 Slider 组件。
  3. 使用 kebab case 命名,例如
    request-path
    或
    context-budget
    。先在注册表中搜索该名称。后续模块注册相同名称时,将替换先前的图表。
  4. 将代码放在名为
    figures-<topic>.js
    的模块文件中。使用 IIFE 包裹代码,读取
    window.LF
    ,如果它不存在则提前返回。
  5. 编写图表函数
    function (host, cfg)
    。它向
    host
    追加一个
    .lf
    卡片,并且可以返回 dispose 函数。
  6. 构建卡片:
    .lf-head
    包含大写的
    .lf-label
    和一段简短提示,
    .lf-body
    放置主体,
    .lf-cap
    放置图注。
  7. SVG 使用
    viewBox="0 0 520 H"
    。大多数课程图表的 H 值为 200 到 250。单个条形所需的 H 值更小。
  8. 添加
    <title>
    和
    <desc>
    ,其 id 只创建一次,并放在任何 render 函数之外。
  9. 对于动画图表,先添加入场动画,再添加一个缓慢循环。逐行遵循
    references/smil-rules.md
    。
  10. 对于 Slider 组件,在调用
    LF.slider
    或
    LF.select
    之前定义
    state._render
    。然后在末尾调用一次
    state._render()
    。
  11. 在模块末尾调用
    LF.register({ 'your-name': fn })
    。
  12. 在课程 Markdown 中添加 fence。第一行放置名称,之后可添加可选的 JSON 配置:
    markdown
    ```figure
    context-budget {"windowK": 32}
    ```
  13. 运行"完成前检查"中的检查项。在浅色主题、深色主题、375 px 宽度以及启用减少动态效果的情况下查看图表。

How the page mounts a figure

页面如何挂载图表

  • The Markdown parser turns the fence into
    <div class="lesson-figure" data-figure="name {json}">
    .
  • The site build scans lesson Markdown for fence names. It finds the module file that contains the quoted name and writes a manifest. A fence name with no provider stops the build.
  • The page loads only the modules that the lesson needs, in a fixed order. New module files go after the listed ones, in alphabetical order.
  • The mount function reads the first word as the name and parses the rest as JSON. Bad JSON gives an empty
    cfg
    .
  • If the figure function throws, the runtime empties the host and logs a warning. The rest of the lesson still renders.
  • After mount, the runtime adds a title, a description,
    role="img"
    , and control labels if they are missing. It adds a Pause button when the figure has SMIL animation, and a Replay button when any animation plays once.
  • The runtime pauses animation when the figure leaves the viewport, when the tab is hidden, and when the reader presses Pause. With reduced motion or print, it shows the static frame.
references/toolkit.md
describes every runtime function and has two complete example modules.
  • Markdown 解析器会将 fence 转换为
    <div class="lesson-figure" data-figure="name {json}">
    。
  • 站点构建流程会扫描课程 Markdown 中的 fence 名称,找到包含带引号名称的模块文件,并写入 manifest。找不到提供模块的 fence 名称会中止构建。
  • 页面只加载课程所需的模块,并按固定顺序加载。新模块文件位于列出的模块之后,并按字母顺序排列。
  • 挂载函数将第一个词读取为名称,并将其余内容解析为 JSON。无效的 JSON 会产生空的
    cfg
    。
  • 如果图表函数抛出异常,运行时会清空宿主元素并记录警告。课程的其余部分仍会正常呈现。
  • 挂载后,如果缺少标题、描述、
    role="img"
    和控件标签,运行时会自动补充。图表包含 SMIL 动画时会添加 Pause 按钮;任何动画仅播放一次时会添加 Replay 按钮。
  • 当图表离开视口、标签页隐藏或读者按下 Pause 时,运行时会暂停动画。启用减少动态效果或进行打印时,则显示静态帧。
references/toolkit.md
描述了每个运行时函数,并提供两个完整示例模块。

Rules

规则

Animated figures:
  1. Use only
    <animate>
    ,
    <animateTransform>
    , and
    <animateMotion>
    . Do not use
    setInterval
    or
    requestAnimationFrame
    in a figure.
  2. Keep each figure at 55 SVG elements or fewer.
  3. Entries go from opacity 0 and scale 0.95 to opacity 1 and scale 1. Never start a scale at 0.
  4. Entries use
    calcMode="spline"
    and
    keySplines="0.23 1 0.32 1"
    . Entry duration is 0.5 to 0.6 s.
  5. Stagger entry begins by 0.05 to 0.4 s. Exits are shorter than entries.
  6. Loops last 2.5 to 6 s and use
    repeatCount="indefinite"
    . Do not set
    fill="freeze"
    on a loop, because the runtime then plays it once.
  7. Each
    keyTimes
    list has as many entries as
    values
    . It starts at 0, ends at 1, and never decreases.
  8. Each
    keySplines
    list has one entry fewer than
    keyTimes
    . Use it only with
    calcMode="spline"
    .
  9. An
    animateMotion
    with
    keyPoints
    uses
    calcMode="linear"
    . Its keyPoints count equals its keyTimes count. It has no
    values
    .
  10. Do not put
    var()
    in an animated
    fill
    or
    stroke
    value. Animate the opacity of a second element that has the target colour.
  11. Loops animate only opacity, transform,
    stroke-dashoffset
    , or motion along a path. The runtime makes any animation of x, y, x1, y1, x2, y2, width, height, r, cx, cy, rx, or ry play once.
  12. The frame at the host's
    data-static-time
    (default 1.5 s) is complete and readable. Set the attribute on the host when a later moment shows the full state.
  13. Scale an element around its centre. Draw the content of a group around (0, 0) and move the group with
    translate
    . Add the scale with
    additive="sum"
    .
Slider widgets:
  1. Write ES5 only:
    var
    , function expressions, string concatenation. No arrow functions,
    let
    ,
    const
    , or template literals.
  2. Define
    state._render
    before the first
    LF.slider
    or
    LF.select
    call. The slider wraps the render function when you create it.
  3. In
    state._render
    , remove all SVG children and add them again. Do not edit nodes in place.
  4. Create ids once, outside
    state._render
    . The runtime removes attributes that the new nodes do not have, ids included.
  5. Grow bars by length or by
    stroke-dasharray
    on a path. Do not grow bars with scale, because reconciled nodes scale from their centre.
  6. Keep each slider label short and lowercase with the unit in brackets, for example
    chunk size (tokens)
    .
Both kinds:
  1. Take every colour from a CSS variable with the light theme value as its default, for example
    var(--blueprint,#3553ff)
    . Use literal hex only when no variable works.
  2. Use at most one accent colour (
    --blueprint
    ) for the main subject and
    --warn
    for one second state. Use ink and rule tokens for the rest.
  3. Set SVG text at 12 units or larger, in
    var(--font-mono)
    . If labels must be smaller, give the SVG a minimum width of 500 px and let it scroll sideways.
  4. Measure label size on a phone. On a 375 px screen, a 520-unit SVG inside the card drew 279 px wide. A 12-unit label then drew at about 6.4 px.
  5. Write the caption in plain technical English. Name what each colour means. Keep sentences at 25 words or fewer.
  6. Give the label in
    .lf-label
    in uppercase, two to four words.
Mechanism figures (tier 2):
  1. Show real names and real numbers: file names, keys, token counts. Never
    item 1
    or a grey bar with no name.
  2. Give the reader one control: step, slider, toggle, play, or stop a part.
  3. End with a verdict line in text, computed from the numbers in the body. Never write a fixed outcome.
  4. Run once when 35 percent of the figure is visible, add a Replay button, and never loop.
  5. Animate
    transform
    and
    opacity
    only, with
    cubic-bezier(0.23, 1, 0.32, 1)
    . Press 120 to 160 ms, reveal 200 to 300 ms, fold 380 to 500 ms.
  6. Stagger lists by 30 to 70 ms per item, for the first 8 items only.
  7. Keep every label whole at every frame: no ellipsis, no overlap, no text on dots. Text 11 px or more, verdict 12.5 px or more.
  8. At 320 px, stack the panels in one column and give each control a 40 px touch target.
  9. Use a mechanism that no other page on the site uses, and add it to the site's mechanism table.
Dither fields (tier 3):
  1. Read the colours from
    --bg
    ,
    --blueprint
    , and
    --ink
    , and redraw when
    data-theme
    changes.
  2. Draw at 30 frames per second at most, and only while the band is visible.
  3. With reduced motion, draw one static frame. Without WebGL, show a static hatch.
  4. Mark the band
    aria-hidden="true"
    and put no text on the dots except the label chip.
动画图表:
  1. 仅使用
    <animate>
    、
    <animateTransform>
    和
    <animateMotion>
    。图表中不得使用
    setInterval
    或
    requestAnimationFrame
    。
  2. 每个图表最多包含 55 个 SVG 元素。
  3. 入场动画从 opacity 0、scale 0.95 过渡到 opacity 1、scale 1。缩放绝不能从 0 开始。
  4. 入场动画使用
    calcMode="spline"
    和
    keySplines="0.23 1 0.32 1"
    。入场时长为 0.5 到 0.6 秒。
  5. 错开入场的开始时间为 0.05 到 0.4 秒。退场时长应短于入场时长。
  6. 循环时长为 2.5 到 6 秒,并使用
    repeatCount="indefinite"
    。不要在循环上设置
    fill="freeze"
    ,否则运行时只会播放一次。
  7. 每个
    keyTimes
    列表必须与
    values
    包含相同数量的元素。它从 0 开始、在 1 结束,且数值不得递减。
  8. 每个
    keySplines
    列表比
    keyTimes
    少一个元素。仅在
    calcMode="spline"
    时使用。
  9. 带
    keyPoints
    的
    animateMotion
    使用
    calcMode="linear"
    。其 keyPoints 数量必须等于 keyTimes 数量,并且没有
    values
    。
  10. 不要在带动画的
    fill
    或
    stroke
    值中使用
    var()
    。应改为动画化第二个元素的不透明度,并为该元素设置目标颜色。
  11. 循环仅可动画化 opacity、transform、
    stroke-dashoffset
    ,或沿路径运动。运行时会让 x、y、x1、y1、x2、y2、width、height、r、cx、cy、rx 或 ry 的任何动画仅播放一次。
  12. 宿主元素
    data-static-time
    (默认 1.5 秒)对应的帧必须完整且可读。如果后续时刻才会显示完整状态,请在宿主元素上设置该属性。
  13. 围绕元素中心进行缩放。围绕 (0, 0) 绘制组内容,再使用
    translate
    移动该组。使用
    additive="sum"
    添加缩放。
Slider 组件:
  1. 仅使用 ES5:
    var
    、函数表达式和字符串拼接。不得使用箭头函数、
    let
    、
    const
    或模板字符串。
  2. 在第一次调用
    LF.slider
    或
    LF.select
    之前定义
    state._render
    。创建 Slider 时,Slider 会包装 render 函数。
  3. 在
    state._render
    中移除所有 SVG 子元素,然后重新添加。不得原地编辑节点。
  4. id 只创建一次,并放在
    state._render
    之外。运行时会移除新节点不具备的属性,包括 id。
  5. 通过长度或路径的
    stroke-dasharray
    增长条形。不要使用 scale 增长条形,因为协调后的节点会从中心开始缩放。
  6. Slider 标签应简短并使用小写字母,将单位放在方括号中,例如
    chunk size (tokens)
    。
两类图表均适用:
  1. 每种颜色都应来自 CSS 变量,并以浅色主题的值作为默认值,例如
    var(--blueprint,#3553ff)
    。仅当没有可用变量时才使用十六进制字面量。
  2. 最多使用一种强调色(
    --blueprint
    )呈现主体,并使用
    --warn
    表示第二种状态。其余部分使用 ink 和 rule token。
  3. SVG 文字应不小于 12 个单位,并使用
    var(--font-mono)
    。如果标签必须更小,请将 SVG 的最小宽度设为 500 px,并允许其横向滚动。
  4. 在手机上测量标签尺寸。在 375 px 屏幕上,520 单位的 SVG 在卡片内绘制为 279 px 宽。12 单位的标签实际绘制尺寸约为 6.4 px。
  5. 使用平实的专业英语编写图注。说明每种颜色的含义。句子不超过 25 个词。
  6. .lf-label
    中的标签使用大写字母,并控制在两到四个词。
机制图示(第二层):
  1. 显示真实名称和真实数值,例如文件名、键和 token 数量。绝不能使用
    item 1
    或没有名称的灰色条形。
  2. 为读者提供一个控件:步骤、Slider、开关、播放或停止某个部分。
  3. 最后用文本给出结论行,并根据主体中的数值计算结论。绝不能写死结果。
  4. 当图表可见度达到 35% 时运行一次,添加 Replay 按钮,并且绝不循环。
  5. 仅动画化 transform 和 opacity,并使用
    cubic-bezier(0.23, 1, 0.32, 1)
    。按下时长为 120 到 160 毫秒,显示时长为 200 到 300 毫秒,折叠时长为 380 到 500 毫秒。
  6. 仅对前 8 个列表项进行错开排列,每项间隔 30 到 70 毫秒。
  7. 每一帧都必须完整显示所有标签:不得使用省略号、不得重叠、不得在圆点上加文字。文字不得小于 11 px,结论不得小于 12.5 px。
  8. 在 320 px 宽度下,将面板堆叠为单列,并为每个控件提供 40 px 的触控目标。
  9. 使用站点中其他页面未曾采用的机制,并将其添加到站点的机制表中。
Dither 场(第三层):
  1. 从
    --bg
    、
    --blueprint
    和
    --ink
    读取颜色,并在
    data-theme
    变化时重新绘制。
  2. 绘制频率最多为每秒 30 帧,并且仅在色带可见时绘制。
  3. 启用减少动态效果时绘制单个静态帧。无法使用 WebGL 时显示静态阴影线纹理。
  4. 将色带标记为
    aria-hidden="true"
    ,并且除标签 chip 外,不得在圆点上放置任何文字。

Check before you finish

完成前检查

  • The fence name matches the registered name exactly, and no other module registers it.
  • The module has no
    =>
    ,
    let
    ,
    const
    , or backtick strings.
  • The module has no
    setInterval
    and no
    requestAnimationFrame
    .
  • The validator in
    references/smil-rules.md
    returns an empty list for the mounted host.
  • Each animated figure has 55 SVG elements or fewer.
  • Every loop has a duration from 2.5 to 6 s.
  • No loop animates a geometry attribute from rule 11.
  • With reduced motion on, the figure shows a complete picture and no element is missing.
  • In dark theme, every line and label is visible.
  • At 375 px width, every label is readable and the page has no sideways scroll outside the figure.
  • For a widget, moving each slider to its minimum and maximum gives no
    NaN
    , no negative widths, and no console errors.
  • The SVG has one title and one description, and their ids stay the same after a slider moves.
  • The caption names every colour that the figure uses.
  • Tier 2: every item in the checklist at the end of
    references/mechanism-figures.md
    passes.
  • Tier 3: every item in the checklist at the end of
    references/dither-fields.md
    passes.
  • fence 名称与注册名称完全一致,并且没有其他模块注册该名称。
  • 模块中不存在
    =>
    、
    let
    、
    const
    或反引号字符串。
  • 模块中不存在
    setInterval
    和
    requestAnimationFrame
    。
  • references/smil-rules.md
    中的验证器针对已挂载的宿主元素返回空列表。
  • 每个动画图表包含不超过 55 个 SVG 元素。
  • 每个循环的时长均为 2.5 到 6 秒。
  • 没有循环动画化规则 11 中列出的几何属性。
  • 启用减少动态效果后,图表显示完整画面,没有元素缺失。
  • 在深色主题下,每条线和每个标签都清晰可见。
  • 在 375 px 宽度下,每个标签都清晰可读,且图表之外没有横向滚动。
  • 对于组件,将每个 Slider 移至最小值和最大值时,不出现
    NaN
    、负宽度或控制台错误。
  • SVG 包含一个 title 和一个 desc,并且 Slider 移动后它们的 id 保持不变。
  • 图注说明了图表使用的每种颜色。
  • 第二层:
    references/mechanism-figures.md
    末尾检查清单中的每一项均通过。
  • 第三层:
    references/dither-fields.md
    末尾检查清单中的每一项均通过。

Files

文件

  • references/smil-rules.md
    : the twelve SMIL rules in full, what each rule prevents, and a validator you can run in the browser console.
  • references/toolkit.md
    : the
    LF
    functions and the mount sequence. It also has a complete slider widget, a complete SMIL figure, and a preview page for use outside the course site.
  • references/tokens.md
    : colour tokens for light and dark themes, fonts, and motion timing values.
  • references/mechanism-figures.md
    : tier 2. Real names, rejected figures, mechanism shapes, anatomy, verdict, motion budget, and checks.
  • references/dither-fields.md
    : tier 3. How the shader draws, the four motions, markup, rules, dithered bars, and checks.
  • templates/mechanism.html
    : a complete tier 2 figure, an LRU cache with a size control, that opens in any browser.
  • templates/dither.js
    : a complete tier 3 script. Load it and add
    <div class="dither" data-seed="...">
    .
Inside the AI Engineering from Scratch repo, also see
site/lesson-figures.js
for the runtime and
site/figures-*.js
for more figures.
  • references/smil-rules.md
    :完整的十二条 SMIL 规则、每条规则可防止的问题,以及可在浏览器控制台运行的验证器。
  • references/toolkit.md
    :
    LF
    函数和挂载顺序。还包含一个完整的 Slider 组件、一个完整的 SMIL 图表,以及可在课程站点之外使用的预览页面。
  • references/tokens.md
    :浅色和深色主题的颜色 token、字体以及动效时序值。
  • references/mechanism-figures.md
    :第二层。真实名称、被否决的图表、机制形状、结构解析、结论、动效预算和检查项。
  • references/dither-fields.md
    :第三层。shader 的绘制方式、四种运动效果、标记、规则、抖动条形和检查项。
  • templates/mechanism.html
    :一个完整的第二层图表——带有大小控件的 LRU cache,可在任意浏览器中打开。
  • templates/dither.js
    :一个完整的第三层脚本。加载它并添加
    <div class="dither" data-seed="...">
    。
在 AI Engineering from Scratch 仓库中,还可参阅
site/lesson-figures.js
中的运行时,以及
site/figures-*.js
中的更多图表。