text-to-lottie

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Authoring Renderable Lottie Files

创作可渲染的Lottie文件

This app renders Lottie with Skia's Skottie module (via
canvaskit-wasm
), not the JS
lottie-web
runtime. Follow the rules below and verify the result.
This skill covers the mechanics — the JSON shape Skottie needs. For the craft (timing, easing, choreography, Disney animation principles), see LottieFiles' motion-design skill. Its guidance is in milliseconds; convert to frames with
frames = ms / 1000 * fr
.
本应用通过
canvaskit-wasm
,使用Skia的Skottie模块渲染Lottie动画,而非JS的
lottie-web
运行时。请遵循以下规则并验证结果。
本技能涵盖的是技术实现——即Skottie所需的JSON结构。至于创作技巧(时序、缓动、编排、迪士尼动画原则),请参阅LottieFiles的运动设计技能。其指导内容以毫秒为单位,可通过
frames = ms / 1000 * fr
转换为帧数。

Setting up the project

项目设置

The deliverable is not just
public/lottie.json
: the viewer should be set up and the animation should be previewable in the browser. If the player project is missing, create it; if it exists, install/update dependencies as needed, start the dev server, and open the local preview URL for verification.
Always use the official GitHub player project — never hand-roll a custom viewer. This skill's JSON rules (slots, the properties panel, the
?frame=
URL controls, the Skottie wasm wiring) only hold inside that exact project. Do not build your own HTML page, swap in
lottie-web
, or scaffold a bespoke canvas setup — any of those will silently diverge from how this player renders and the verification steps below won't apply. If the player project isn't already on this machine, scaffold a fresh copy of the repo with degit:
bash
npx degit diffusionstudio/lottie my-animation
cd my-animation
npm install   # postinstall copies the CanvasKit wasm into /public
npm run dev
Then open the printed local URL. If you already have the project, just
npm install && npm run dev
.
交付成果不只是
public/lottie.json
:需要搭建好查看器,确保动画可在浏览器中预览。如果播放器项目缺失,请创建它;如果已存在,请按需安装/更新依赖,启动开发服务器,并打开本地预览URL进行验证。
请始终使用官方GitHub播放器项目——切勿自行编写自定义查看器。本技能的JSON规则(插槽、属性面板、
?frame=
URL控制、Skottie wasm连接)仅在该特定项目中生效。请勿构建自己的HTML页面、替换为
lottie-web
或搭建定制化canvas环境——任何此类操作都会导致与本播放器的渲染方式产生隐性差异,且下文的验证步骤将不再适用。如果本机上没有该播放器项目,请使用
degit
克隆仓库的全新副本:
bash
npx degit diffusionstudio/lottie my-animation
cd my-animation
npm install   # postinstall会将CanvasKit wasm复制到/public目录
npm run dev
然后打开打印出的本地URL。如果已有该项目,只需执行
npm install && npm run dev
即可。

Where to write the file (and how it loads)

文件编写位置(及加载方式)

  • Write the animation JSON to
    public/lottie.json
    . That is the only file you need to touch to change what the app shows —
    src/App.tsx
    fetches
    /lottie.json
    at startup.
  • With the dev server running (
    npm run dev
    ), a Vite plugin watches that file and full-reloads the page on save, so your edit appears immediately. No other wiring is required.
  • If parsing fails, the app shows the error on screen ("CanvasKit could not parse the Lottie file.").
  • 将动画JSON写入**
    public/lottie.json
    **。这是唯一需要修改的文件,用于更改应用显示内容——
    src/App.tsx
    会在启动时获取
    /lottie.json
  • 开发服务器运行时(
    npm run dev
    ),Vite插件会监听该文件,保存后自动重载页面,因此你的修改会立即生效。无需其他配置。
  • 如果解析失败,应用会在屏幕上显示错误信息(“CanvasKit无法解析Lottie文件。”)。

Required top-level shape

必需的顶层结构

Every Lottie document is one JSON object with at least these fields:
jsonc
{
  "v": "5.7.0",      // bodymovin version string
  "fr": 60,          // frame rate (fps)
  "ip": 0,           // in point (start frame)
  "op": 120,         // out point (end frame) — duration = (op - ip) / fr seconds
  "w": 512,          // composition width  (px)
  "h": 512,          // composition height (px)
  "assets": [],      // images / precomps; [] if none
  "layers": [ /* ... */ ]
}
The app letterboxes the
w
×
h
composition to fit the canvas, so pick a square or sensible aspect ratio.
op
controls the total frame count shown in the UI.
每个Lottie文档都是一个JSON对象,至少包含以下字段:
jsonc
{
  "v": "5.7.0",      // bodymovin版本字符串
  "fr": 60,          // 帧率(fps)
  "ip": 0,           // 入点(起始帧)
  "op": 120,         // 出点(结束帧)——时长 = (op - ip) / fr 秒
  "w": 512,          // 合成宽度(像素)
  "h": 512,          // 合成高度(像素)
  "assets": [],      // 图片/预合成;无则为[]
  "layers": [ /* ... */ ]
}
应用会将
w
×
h
的合成内容添加黑边以适配画布,因此请选择正方形或合理的宽高比。
op
控制UI中显示的总帧数。

Layers

图层

layers
follows After Effects order: the first entry in the array is the topmost layer, and later entries render underneath it. Each layer needs at minimum:
jsonc
{
  "ty": 4,           // layer type: 4 = shape layer (the common case)
  "nm": "circle",    // name (optional but helpful)
  "ip": 0,           // layer in point
  "op": 120,         // layer out point — must cover the frames you want it visible
  "st": 0,           // start time
  "ks": { /* transform — see below */ },
  "shapes": [ /* ... */ ]   // for shape layers
}
Common layer types:
4
shape,
2
image,
1
solid,
0
precomp,
5
text. Prefer shape layers (
ty: 4
)
for LLM-authored animations — no external assets needed.
layers
遵循After Effects的顺序:数组中的第一个条目最顶层的图层,后续条目在其下方渲染。每个图层至少需要包含以下内容:
jsonc
{
  "ty": 4,           // 图层类型:4 = 形状图层(常见情况)
  "nm": "circle",    // 名称(可选但有助于识别)
  "ip": 0,           // 图层入点
  "op": 120,         // 图层出点——必须覆盖你希望其可见的帧范围
  "st": 0,           // 起始时间
  "ks": { /* 变换——见下文 */ },
  "shapes": [ /* ... */ ]   // 形状图层专用
}
常见图层类型:
4
形状、
2
图片、
1
纯色、
0
预合成、
5
文本。对于LLM创作的动画,优先选择形状图层(
ty: 4
——无需外部资源。

The transform block (
ks
)

变换块(
ks

Every layer has a transform. Each property is either static (
{ "a": 0, "k": value }
) or animated (
{ "a": 1, "k": [ ...keyframes ] }
).
jsonc
"ks": {
  "o": { "a": 0, "k": 100 },                 // opacity 0–100
  "r": { "a": 0, "k": 0 },                   // rotation (degrees)
  "p": { "a": 0, "k": [256, 256, 0] },       // position [x, y, z]
  "a": { "a": 0, "k": [0, 0, 0] },           // anchor point [x, y, z]
  "s": { "a": 0, "k": [100, 100, 100] }      // scale (percent, per axis)
}
Anchor matters: rotation and scale pivot around the anchor
a
, expressed in the layer's own coordinate space. To rotate a shape around its own center, set the shape's geometry around the anchor (e.g. center the ellipse on
a
).
每个图层都有变换属性。每个属性要么是静态的(
{ "a": 0, "k": value }
),要么是动态的(
{ "a": 1, "k": [ ...关键帧 ] }
)。
jsonc
"ks": {
  "o": { "a": 0, "k": 100 },                 // 透明度 0–100
  "r": { "a": 0, "k": 0 },                   // 旋转(度数)
  "p": { "a": 0, "k": [256, 256, 0] },       // 位置 [x, y, z]
  "a": { "a": 0, "k": [0, 0, 0] },           // 锚点 [x, y, z]
  "s": { "a": 0, "k": [100, 100, 100] }      // 缩放(百分比,按轴)
}
锚点很重要:旋转和缩放围绕锚点
a
进行,锚点以图层自身的坐标空间表示。要让形状围绕自身中心旋转,请将形状的几何中心与锚点对齐(例如,将椭圆中心设置在
a
点)。

Shapes — the #1 Skottie gotcha

形状——Skottie最容易出错的点

Skottie requires shape elements to be wrapped in a Group (
ty: "gr"
).
A flat list of shapes + fills directly in
shapes
renders blank. Always nest the geometry, fill/stroke, and a group transform inside a group's
it
array:
jsonc
"shapes": [
  {
    "ty": "gr",            // GROUP — required wrapper
    "nm": "ball",
    "it": [
      {
        "ty": "el",        // ellipse
        "p": { "a": 0, "k": [0, 0] },
        "s": { "a": 0, "k": [120, 120] }
      },
      {
        "ty": "fl",        // fill
        "c": { "a": 0, "k": [0.2, 0.6, 1, 1] },   // RGBA, each 0–1
        "o": { "a": 0, "k": 100 }
      },
      {
        "ty": "tr",        // GROUP TRANSFORM — include even if identity
        "p": { "a": 0, "k": [0, 0] },
        "a": { "a": 0, "k": [0, 0] },
        "s": { "a": 0, "k": [100, 100] },
        "r": { "a": 0, "k": 0 },
        "o": { "a": 0, "k": 100 }
      }
    ]
  }
]
Shape primitives inside
it
:
  • "el"
    ellipse —
    p
    center,
    s
    [width, height]
  • "rc"
    rectangle —
    p
    center,
    s
    [w, h],
    r
    corner radius
  • "sh"
    custom path —
    ks.k
    is a bezier
    { "c": closed?, "v": verts, "i": inTangents, "o": outTangents }
  • "st"
    stroke —
    c
    color,
    w
    width,
    o
    opacity
  • "fl"
    fill —
    c
    color (RGBA 0–1),
    o
    opacity
  • "tr"
    the group's transform (always include it last)
Colors are normalized 0–1 RGBA, not 0–255.
[1, 0, 0, 1]
is opaque red.
Skottie要求形状元素必须包裹在Group(
ty: "gr"
)中。直接在
shapes
中放置形状+填充的扁平列表会导致
空白渲染
。请始终将几何图形、填充/描边和组变换嵌套在组的
it
数组中:
jsonc
"shapes": [
  {
    "ty": "gr",            // GROUP——必需的包裹容器
    "nm": "ball",
    "it": [
      {
        "ty": "el",        // 椭圆
        "p": { "a": 0, "k": [0, 0] },
        "s": { "a": 0, "k": [120, 120] }
      },
      {
        "ty": "fl",        // 填充
        "c": { "a": 0, "k": [0.2, 0.6, 1, 1] },   // RGBA,每个值0–1
        "o": { "a": 0, "k": 100 }
      },
      {
        "ty": "tr",        // 组变换——即使是默认值也请包含
        "p": { "a": 0, "k": [0, 0] },
        "a": { "a": 0, "k": [0, 0] },
        "s": { "a": 0, "k": [100, 100] },
        "r": { "a": 0, "k": 0 },
        "o": { "a": 0, "k": 100 }
      }
    ]
  }
]
it
中的形状原语:
  • "el"
    椭圆——
    p
    为中心,
    s
    为[宽度, 高度]
  • "rc"
    矩形——
    p
    为中心,
    s
    为[宽, 高],
    r
    为圆角半径
  • "sh"
    自定义路径——
    ks.k
    为贝塞尔曲线
    { "c": 是否闭合?, "v": 顶点, "i": 入切线, "o": 出切线 }
  • "st"
    描边——
    c
    为颜色,
    w
    为宽度,
    o
    为透明度
  • "fl"
    填充——
    c
    为颜色(RGBA 0–1),
    o
    为透明度
  • "tr"
    组的变换(请始终放在最后)
颜色为归一化的0–1 RGBA值,而非0–255。
[1, 0, 0, 1]
表示不透明红色。

Animating a property (keyframes)

为属性添加动画(关键帧)

Set
"a": 1
and make
k
an array of keyframe objects. Each keyframe has a time
t
(frame), a value
s
(start value for that segment, as an array), and easing handles
i
/
o
:
jsonc
"p": {
  "a": 1,
  "k": [
    { "t": 0,   "s": [256, 120], "i": { "x": [0.5], "y": [1] }, "o": { "x": [0.5], "y": [0] } },
    { "t": 60,  "s": [256, 400], "i": { "x": [0.5], "y": [1] }, "o": { "x": [0.5], "y": [0] } },
    { "t": 120, "s": [256, 120] }
  ]
}
  • t
    is the frame number; the last keyframe usually has no
    i
    /
    o
    /easing pair beyond
    s
    (it's the end).
  • s
    is always an array, even for scalars like rotation:
    "s": [360]
    .
  • i
    /
    o
    are the bezier ease handles (incoming / outgoing).
    x
    /
    y
    arrays in
    [0..1]
    . For a smooth ease use
    x:[0.5], y:[1]
    (in) and
    x:[0.5], y:[0]
    (out); for linear use
    x:[0], y:[0]
    /
    x:[1], y:[1]
    . Multi-dimensional values may use per-axis arrays.
  • To loop seamlessly, make the last keyframe's value equal the first.
设置
"a": 1
并将
k
设为关键帧对象数组。每个关键帧包含时间
t
(帧数)、值
s
(该片段的起始值,为数组)和缓动控制
i
/
o
jsonc
"p": {
  "a": 1,
  "k": [
    { "t": 0,   "s": [256, 120], "i": { "x": [0.5], "y": [1] }, "o": { "x": [0.5], "y": [0] } },
    { "t": 60,  "s": [256, 400], "i": { "x": [0.5], "y": [1] }, "o": { "x": [0.5], "y": [0] } },
    { "t": 120, "s": [256, 120] }
  ]
}
  • t
    为帧编号;最后一个关键帧通常除了
    s
    之外没有
    i
    /
    o
    /缓动参数(它是结束帧)。
  • s
    始终是数组,即使是旋转这样的标量:
    "s": [360]
  • i
    /
    o
    是贝塞尔缓动控制(入/出)。
    x
    /
    y
    数组的值在
    [0..1]
    范围内。平滑缓动请使用
    x:[0.5], y:[1]
    (入)和
    x:[0.5], y:[0]
    (出);线性缓动请使用
    x:[0], y:[0]
    /
    x:[1], y:[1]
    。多维值可使用按轴的数组。
  • 要实现无缝循环,请让最后一个关键帧的值与第一个关键帧的值相同。

Exposing editable properties (slots + the properties panel)

暴露可编辑属性(插槽+属性面板)

The app can render a live properties panel (text inputs and sliders) that edit chosen values of the animation in real time. This rides on Skottie's native slot feature — no re-parse, the change shows on the next frame.
To make a property editable, do two things:
1. Declare a slot in the Lottie JSON. Add a top-level
"slots"
object whose keys are slot IDs, and point a property at one with
"sid"
instead of (or alongside) an inline value. The slot's
"p"
holds the default, in the same shape the property would normally take.
jsonc
{
  "v": "5.7.0", "fr": 60, "ip": 0, "op": 90, "w": 512, "h": 512, "assets": [],
  "slots": {
    "ballColor": { "p": { "a": 0, "k": [0.231, 0.6, 1, 1] } },   // color: RGBA 0–1
    "ballSize":  { "p": { "a": 0, "k": 120 } }                    // scalar
  },
  "layers": [ /* ... */
    // in the fill:    "c": { "sid": "ballColor" }
    // in a scalar:    "s": { "sid": "ballSize" }
  ]
}
Slot types map to controls like this:
Slot valueControl rendered
scalar (a single number)slider
color (RGBA 0–1)color picker
vec2 (
[x, y]
)
two number inputs
text (a string)text input
The app discovers slots automatically via Skottie's
getSlotInfo()
— you do not list them anywhere else for them to work. The panel appears as soon as the animation declares at least one slot.
应用可渲染实时属性面板(文本输入框和滑块),用于实时编辑动画的选定值。这基于Skottie的原生插槽功能——无需重新解析,更改会在下一帧显示。
要让属性可编辑,请执行两步操作:
**1. 在Lottie JSON中声明插槽。**添加顶层
"slots"
对象,其键为插槽ID,并通过
"sid"
而非(或同时)内联值指向某个属性。插槽的
"p"
保存默认值,格式与属性通常的格式一致。
jsonc
{
  "v": "5.7.0", "fr": 60, "ip": 0, "op": 90, "w": 512, "h": 512, "assets": [],
  "slots": {
    "ballColor": { "p": { "a": 0, "k": [0.231, 0.6, 1, 1] } },   // 颜色:RGBA 0–1
    "ballSize":  { "p": { "a": 0, "k": 120 } }                    // 标量
  },
  "layers": [ /* ... */
    // 在填充中:    "c": { "sid": "ballColor" }
    // 在标量中:    "s": { "sid": "ballSize" }
  ]
}
插槽类型对应的控件如下:
插槽值类型渲染的控件
标量(单个数字)滑块
颜色(RGBA 0–1)颜色选择器
二维向量(
[x, y]
两个数字输入框
文本(字符串)文本输入框
应用通过Skottie的
getSlotInfo()
自动发现插槽——你无需在其他地方列出它们即可生效。只要动画声明了至少一个插槽,面板就会显示。

Required: a background-color control on every animation

必需:每个动画都要有背景颜色控件

Every animation you produce must expose at least one control for the background color. The player does not paint a composition background of its own, so add a full-composition background layer as the last entry in
layers
(so it renders underneath everything), fill it with a slotted color, and label that slot in
controls.json
. Use a rectangle the size of the composition:
jsonc
// last layer in `layers`:
{
  "ty": 4, "nm": "background", "ip": 0, "op": 120, "st": 0,
  "ks": { "o": { "a": 0, "k": 100 }, "p": { "a": 0, "k": [256, 256, 0] },
          "a": { "a": 0, "k": [0, 0, 0] }, "s": { "a": 0, "k": [100, 100, 100] },
          "r": { "a": 0, "k": 0 } },
  "shapes": [
    { "ty": "gr", "it": [
      { "ty": "rc", "p": { "a": 0, "k": [256, 256] },
        "s": { "a": 0, "k": [512, 512] }, "r": { "a": 0, "k": 0 } },
      { "ty": "fl", "c": { "sid": "bgColor" }, "o": { "a": 0, "k": 100 } },
      { "ty": "tr", "p": { "a": 0, "k": [0, 0] }, "a": { "a": 0, "k": [0, 0] },
        "s": { "a": 0, "k": [100, 100] }, "r": { "a": 0, "k": 0 },
        "o": { "a": 0, "k": 100 } }
    ] }
}
jsonc
// slots:    "bgColor": { "p": { "a": 0, "k": [1, 1, 1, 1] } }   // default white
// controls: { "sid": "bgColor", "label": "Background color" }
Match the rectangle's
p
/
s
to your composition's
w
×
h
. This is in addition to whatever other controls the animation exposes.
2. (Optional) Describe presentation in
public/controls.json
.
Slots only expose an ID and type, not a label or a sensible slider range. The sidecar file adds that. It is optional — missing entries fall back to the slot ID and a generic 0–100 range. Like
lottie.json
, it hot-reloads on save.
jsonc
{
  "controls": [
    { "sid": "ballColor", "label": "Ball color" },
    { "sid": "ballSize",  "label": "Ball size", "min": 40, "max": 240, "step": 1 }
  ]
}
  • sid
    must match a slot ID exactly.
  • label
    is the display name;
    min
    /
    max
    /
    step
    shape scalar sliders and vec2 inputs (ignored for color/text).
  • An entry whose
    sid
    matches no slot is simply ignored; a slot with no entry still renders with defaults.
你制作的每个动画都必须至少暴露一个背景颜色控件。播放器本身不会绘制合成背景,因此请添加一个覆盖整个合成的背景图层作为
layers
中的
最后一个条目
(使其在所有内容下方渲染),用带插槽的颜色填充它,并在
controls.json
中为该插槽添加标签。使用与合成尺寸相同的矩形:
jsonc
// `layers`中的最后一个图层:
{
  "ty": 4, "nm": "background", "ip": 0, "op": 120, "st": 0,
  "ks": { "o": { "a": 0, "k": 100 }, "p": { "a": 0, "k": [256, 256, 0] },
          "a": { "a": 0, "k": [0, 0, 0] }, "s": { "a": 0, "k": [100, 100, 100] },
          "r": { "a": 0, "k": 0 } },
  "shapes": [
    { "ty": "gr", "it": [
      { "ty": "rc", "p": { "a": 0, "k": [256, 256] },
        "s": { "a": 0, "k": [512, 512] }, "r": { "a": 0, "k": 0 } },
      { "ty": "fl", "c": { "sid": "bgColor" }, "o": { "a": 0, "k": 100 } },
      { "ty": "tr", "p": { "a": 0, "k": [0, 0] }, "a": { "a": 0, "k": [0, 0] },
        "s": { "a": 0, "k": [100, 100] }, "r": { "a": 0, "k": 0 },
        "o": { "a": 0, "k": 100 } }
    ] }
}
jsonc
// 插槽:    "bgColor": { "p": { "a": 0, "k": [1, 1, 1, 1] } }   // 默认白色
// 控件: { "sid": "bgColor", "label": "Background color" }
请将矩形的
p
/
s
与合成的
w
×
h
匹配。这是除动画暴露的其他控件之外必须添加的内容。
**2.(可选)在
public/controls.json
中描述展示信息。**插槽仅暴露ID和类型,不包含标签或合理的滑块范围。这个附属文件可添加这些信息。它是可选的——缺失的条目会回退到插槽ID和通用的0–100范围。与
lottie.json
一样,保存后会自动重载。
jsonc
{
  "controls": [
    { "sid": "ballColor", "label": "Ball color" },
    { "sid": "ballSize",  "label": "Ball size", "min": 40, "max": 240, "step": 1 }
  ]
}
  • sid
    必须与插槽ID完全匹配。
  • label
    是显示名称;
    min
    /
    max
    /
    step
    用于设置标量滑块和二维向量输入框的范围(对颜色/文本无效)。
  • sid
    与任何插槽不匹配的条目会被忽略;没有对应条目的插槽仍会使用默认值渲染。

Controlling playback from a browser agent

通过浏览器代理控制播放

When you drive the page through a browser tool, do not pixel-drag the slider or hunt for the play button — it's unreliable and you can't land on an exact frame. Instead, pin the frame in the URL and read the canvas by its test id:
http://localhost:5173/?frame=60&paused=1
  • ?frame=N
    seeks to frame
    N
    on load and holds it paused, so the moment sits still for a screenshot. This is the right way to inspect a specific frame (e.g. "is the ball at the bottom at frame 60?"): open
    ?frame=60
    , then screenshot.
  • ?paused=1
    starts paused (at frame 0, or at
    frame
    if also given);
    ?paused=0
    forces autoplay even with a frame pinned.
  • With no query params the animation autoplays as usual.
To change the inspected frame, navigate to a new URL (or just edit the query string and reload). The canvas carries
data-testid="lottie-canvas"
, so a browser tool can target it directly for screenshots. If the canvas is blank, the page hasn't finished loading or the Lottie failed to parse (check the on-screen error).
当你通过浏览器工具操作页面时,不要拖动滑块或寻找播放按钮——这不可靠且无法精确定位到某一帧。相反,请在URL中固定帧并通过测试ID读取画布:
http://localhost:5173/?frame=60&paused=1
  • ?frame=N
    会在加载时跳转到第
    N
    帧并保持暂停状态,以便截图查看该帧。这是检查特定帧的正确方式(例如“第60帧时球是否在底部?”):打开
    ?frame=60
    ,然后截图。
  • ?paused=1
    启动时处于暂停状态(在第0帧,或同时指定
    frame
    时在该帧);
    ?paused=0
    强制自动播放,即使已固定帧。
  • 无查询参数时,动画会正常自动播放。
要更改检查的帧,请导航到新URL(或直接编辑查询字符串并重新加载)。画布带有
data-testid="lottie-canvas"
,因此浏览器工具可直接定位它进行截图。如果画布为空,说明页面尚未加载完成或Lottie解析失败(请检查屏幕上的错误信息)。

Before you finish — checklist

完成前的检查清单

  1. The file is valid JSON (no comments, no trailing commas). Validate with
    node -e "JSON.parse(require('fs').readFileSync('public/lottie.json','utf8'))"
    .
  2. Every shape primitive/fill is inside a
    "ty": "gr"
    group's
    it
    array, and each group ends with a
    "tr"
    transform.
  3. Top-level
    op
    and each layer's
    op
    cover the frames you animate.
  4. Colors are 0–1 RGBA; positions/sizes are within the
    w
    ×
    h
    composition.
  5. Keyframe
    s
    values are arrays; loops repeat the first value at the end.
  6. A background-color control is present: a full-composition background layer (last in
    layers
    ) with a slotted fill (e.g.
    bgColor
    ) and a matching
    controls.json
    label.
  7. The project is the official GitHub player (scaffolded via degit), not a custom/hand-rolled viewer.
  8. If the dev server is running, just save — it hot-reloads. Otherwise start it with
    npm run dev
    . A blank canvas (no error) → re-check the group wrapping.
  9. The player is running and the preview URL has been opened or reported. When a browser tool is available, verify the page shows a nonblank rendered animation before finalizing — pin a key frame via the URL (see "Controlling playback from a browser agent"), e.g. open
    ?frame=60&paused=1
    and screenshot, rather than dragging the on-screen slider.
  1. 文件是有效的JSON(无注释,无尾随逗号)。可使用
    node -e "JSON.parse(require('fs').readFileSync('public/lottie.json','utf8'))"
    验证。
  2. 每个形状原语/填充都在
    "ty": "gr"
    组的
    it
    数组内,且每个组都以
    "tr"
    变换结尾。
  3. 顶层
    op
    和每个图层的
    op
    覆盖了你制作动画的帧范围。
  4. 颜色为0–1 RGBA值;位置/尺寸在
    w
    ×
    h
    的合成范围内。
  5. 关键帧的
    s
    值是数组;循环动画的最后一个值与第一个值相同。
  6. 存在背景颜色控件:一个覆盖整个合成的背景图层(位于
    layers
    最后),带有带插槽的填充(例如
    bgColor
    ),并在
    controls.json
    中有匹配的标签。
  7. 项目是官方GitHub播放器(通过degit搭建),而非自定义/自行编写的查看器。
  8. 如果开发服务器正在运行,只需保存即可——它会自动重载。否则请用
    npm run dev
    启动。空白画布(无错误)→重新检查组包裹情况。
  9. 播放器正在运行,且已打开或报告预览URL。当有浏览器工具可用时,请在最终确定前验证页面显示非空白的渲染动画——通过URL固定关键帧(请参阅“通过浏览器代理控制播放”),例如打开
    ?frame=60&paused=1
    并截图,而非拖动屏幕上的滑块。