greenlight-motion 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -9
- package/dist/greenlight-motion-script.mjs +260 -190
- package/dist/greenlight-motion.js +570 -570
- package/dist/greenlight-motion.mjs +29205 -29174
- package/package.json +1 -1
- package/schema/capabilities.json +1 -1
- package/skill/SKILL.md +11 -11
- package/skill/references/scene-script.md +2 -2
- package/skill/references/video-design.md +5 -2
- package/skill/references/video-grid.md +2 -2
- package/skill/references/video-keyframes.md +4 -3
- package/skill/references/video-text-kinetic.md +4 -4
- package/skill/references/video-text-presets.md +16 -16
- package/skill/references/video-text.md +8 -8
package/skill/SKILL.md
CHANGED
|
@@ -18,7 +18,7 @@ You never write UI or animation code. If something is not in the format, it is n
|
|
|
18
18
|
## Setup (once per machine)
|
|
19
19
|
|
|
20
20
|
```
|
|
21
|
-
npx greenlight-motion@0.3.
|
|
21
|
+
npx greenlight-motion@0.3.2 doctor
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
It checks Node 18+, Chrome or Edge, WebGPU and H.264 encoding, and prints a fix for anything missing. Do not install
|
|
@@ -39,7 +39,7 @@ animation presets (the same converter the GreenLight Motion connector uses in Cl
|
|
|
39
39
|
keyframes rarely look as good. The format, the design rules and the catalogues: `skill/references/scene-script.md`.
|
|
40
40
|
|
|
41
41
|
```
|
|
42
|
-
npx greenlight-motion@0.3.
|
|
42
|
+
npx greenlight-motion@0.3.2 script <folder> --from scenes.json # or write <folder>/script.json, then: script <folder>
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
Then `check` and `stills` (below), fix the SCRIPT and run `script` again — it rewrites `project.json`. A scene's
|
|
@@ -85,14 +85,14 @@ What the engine does there, so you don't learn it from a broken frame:
|
|
|
85
85
|
|
|
86
86
|
## Workflow
|
|
87
87
|
|
|
88
|
-
1. `npx greenlight-motion@0.3.
|
|
88
|
+
1. `npx greenlight-motion@0.3.2 init <folder>` — starts from a working example (title, subtitle, accent line, four
|
|
89
89
|
options). `--from file.json` starts from a project you have (for example one exported from GreenLight Dash).
|
|
90
90
|
2. Edit `<folder>/project.json` — for changes to an EXISTING project prefer `apply` (below): it checks every edit and
|
|
91
91
|
applies all or nothing. Put pictures, video, sound and fonts in `<folder>/assets/` and refer to them as
|
|
92
92
|
`"asset:<file>"` (e.g. `"url": "asset:product.png"`).
|
|
93
|
-
3. `npx greenlight-motion@0.3.
|
|
93
|
+
3. `npx greenlight-motion@0.3.2 check <folder>` — fix everything it lists (missing files, template mistakes, blank
|
|
94
94
|
frames, page errors), and read its notes: text the engine wraps where you did not break it. `--json` for machine output.
|
|
95
|
-
4. `npx greenlight-motion@0.3.
|
|
95
|
+
4. `npx greenlight-motion@0.3.2 stills <folder>` — renders frames and **a labelled contact sheet**. Open and look at
|
|
96
96
|
it before you go on: layout, readability, timing. Fix and repeat. `--at 0.5,1.2,3` for exact times.
|
|
97
97
|
5. Hand it over: tell the user to open `<folder>/index.html` (Chrome or Edge), or `pack` it into one file, or
|
|
98
98
|
`render` the MP4 yourself (`--fps 60 --motion-blur` for fast motion).
|
|
@@ -106,7 +106,7 @@ the error names the edit number with a fix. Ops:
|
|
|
106
106
|
[{ "op": "set", "item": "title", "path": "textContent", "value": "Launch day" },
|
|
107
107
|
{ "op": "set", "project": true, "path": "videoSize.w", "value": 1080 },
|
|
108
108
|
{ "op": "unset", "item": "title", "path": "propertyKeyframes.opacity" },
|
|
109
|
-
{ "op": "keyframe", "item": "accent", "track": "translateX", "at": 50, "value": 120, "easing": "
|
|
109
|
+
{ "op": "keyframe", "item": "accent", "track": "translateX", "at": 50, "value": 120, "easing": "Ease Out" },
|
|
110
110
|
{ "op": "add", "to": "clips", "value": { "id": "c9", "mediaType": "image", "url": "asset:a.png", "duration": 4 } },
|
|
111
111
|
{ "op": "add", "to": "channels", "value": { "id": "ch9" }, "at": 0 },
|
|
112
112
|
{ "op": "add", "to": { "channel": "ch9" }, "value": { "id": "it9", "clipId": "c9", "trimStart": 0, "trimEnd": 4 } },
|
|
@@ -157,7 +157,7 @@ editor's own normalizer), so write only what you mean.
|
|
|
157
157
|
Full references (generated from the editor's own docs; ignore the `/api/` routes they mention):
|
|
158
158
|
`skill/references/` — video-design, scene-script, video-projects, video-text, video-text-kinetic, video-text-presets, video-shapes, video-keyframes,
|
|
159
159
|
video-camera, video-3d, video-effects, video-transitions, video-particles, video-paths, video-backgrounds, video-grid.
|
|
160
|
-
Machine-readable lists: `npx greenlight-motion@0.3.
|
|
160
|
+
Machine-readable lists: `npx greenlight-motion@0.3.2 schema effects | transitions | easings | paths | expressions`.
|
|
161
161
|
|
|
162
162
|
## Template
|
|
163
163
|
|
|
@@ -204,7 +204,7 @@ an absolute moment; `align` `sync` (default) / `start` / `end`; `offset` seconds
|
|
|
204
204
|
|
|
205
205
|
The library is 77 hand-picked sounds in categories (whooshes and swooshes, transitions, clicks, pop-ups and
|
|
206
206
|
notifications, data blips, typing and writing, foley, bubbles, impacts and bass drops, camera, gears, voice clips).
|
|
207
|
-
`npx greenlight-motion@0.3.
|
|
207
|
+
`npx greenlight-motion@0.3.2 schema sounds` lists every one with its `category`, `use` (what it is for), `duration`
|
|
208
208
|
and `sync`. Pick by `category` and `use`, then by name.
|
|
209
209
|
|
|
210
210
|
- **Where the files come from:** the GreenLight sound CDN. `build` downloads each sound a cue uses into
|
|
@@ -220,7 +220,7 @@ The page has **Notes**: the user marks what should change right on the frame (a
|
|
|
220
220
|
and writes a note for each mark. Every note carries the moment (seconds and frame), the mark in composition pixels
|
|
221
221
|
and the layers under it (item ids in project.json), so you change exactly that and nothing else.
|
|
222
222
|
|
|
223
|
-
- **They review on this computer:** run `npx greenlight-motion@0.3.
|
|
223
|
+
- **They review on this computer:** run `npx greenlight-motion@0.3.2 review <folder>` and give them the URL it prints
|
|
224
224
|
(it keeps running; `--open` opens their browser, only when they ask). Their notes land in `<folder>/review/`: read
|
|
225
225
|
`review/NOTES.md`, look at the `at-<t>s.png` pictures (the marks are numbered), make the changes (`apply`), `build`
|
|
226
226
|
again and tell them to reload the page.
|
|
@@ -249,11 +249,11 @@ that fails (`plugin`); look at `stills` for the look. A package that carries its
|
|
|
249
249
|
|
|
250
250
|
The same project opens in GreenLight Dash (the desktop editor this engine comes from) for full editing: the page's
|
|
251
251
|
edit note offers **Open in GreenLight Dash** (it imports the folder as a new project on the open board; a page with
|
|
252
|
-
changes saves a `.glvideo`). `npx greenlight-motion@0.3.
|
|
252
|
+
changes saves a `.glvideo`). `npx greenlight-motion@0.3.2 pack <folder> --glvideo` writes that file yourself: ONE
|
|
253
253
|
`.glvideo` (the project + its files) that opens in GreenLight Dash on a double-click, or dropped on its board. Hand it
|
|
254
254
|
over when the user wants to keep editing in the app. A
|
|
255
255
|
GreenLight Dash project comes the other way through the app's **Export for agents** — a ready folder like the one
|
|
256
|
-
`init` makes, with the options the author ticked. `npx greenlight-motion@0.3.
|
|
256
|
+
`init` makes, with the options the author ticked. `npx greenlight-motion@0.3.2 init <folder> --from <its project.json>`
|
|
257
257
|
starts from one too. Never tell the user they must install it: the page plays, changes options and renders on its own.
|
|
258
258
|
|
|
259
259
|
## Files
|
|
@@ -69,7 +69,7 @@ matte, masks, particles, 3D) goes on from `project.json`: SKILL.md, "Beyond the
|
|
|
69
69
|
`startAt` (s into the file) and `volume` (0–100, default muted). No entrance unless you set `enter`.
|
|
70
70
|
- **Keyframes on any element** — your own motion: `"keyframes": { "x": [[0, -400], [0.8, 0, "Smooth Glide"]], "scale": [[0, 0.9], [2, 1.05]] }`
|
|
71
71
|
— tracks x, y (px offsets from `at`), scale, rotate (deg), opacity (0–1); each key [seconds into the element, value, easing of the
|
|
72
|
-
segment after it — Smooth Glide, AE Smooth, Expo Out, Back Out, Elastic, Linear …]. They replace an entrance's keys on the same track;
|
|
72
|
+
segment after it — Smooth Glide, AE Smooth, Expo Out, Power, Punch, Apple Out, Back Out, Elastic, Linear …]. They replace an entrance's keys on the same track;
|
|
73
73
|
one key holds that value for the whole element.
|
|
74
74
|
- **Every element**: `start` / `end` (s within its scene; default: staggered 0.12 s, to the scene's end), `enter` / `exit` (keyframe presets, `direction` up | down | left | right
|
|
75
75
|
for directional ones), `effects`: [{ "id", "params"? }], `sound` (played at its start), `id`, `label` (its name in the page's options), `opacity` (0–1),
|
|
@@ -126,7 +126,7 @@ the first version and check every version against it.
|
|
|
126
126
|
|
|
127
127
|
**Zoom feels** (`camera.feel`): `studio` Studio · `calm` Calm · `precise` Precise · `lively` Lively · `follow` Follow. Full camera layers (paths, Smart Zoom on a recording's clicks, the drawn cursor): references/video-camera.md.
|
|
128
128
|
|
|
129
|
-
**Overlay effects** (`effects`): `glow`, ★ `bloom`, `auraBlur`, `gradientBeam`, ★ `gradientSweep`, `fractalNoise`, ★ `rgbSplit`, `glitch`, `scanlines`, `flashBlink`, `vhs`, `fisheye`, `opticsCompensation`, `vignette`, ★ `echo`, `timeshift`, `radialBlur`, ★ `radialFastBlur`, `sharpen`, `mirror`, `waveWarp`, `warpStyles`, `shockwave`, `waveLines`, `waveRipple`, `fill`, `shapeRulers`, `copyColor`, `curves`, `turbulentDisplace`, `alphaChoker`, `extract`, ★ `colorama`, `posterize`, ★ `halftone`, ★ `fastCameraWiggle`, ★ `lightRays`, `longShadow`, `outlineBands`, `kaleidoscope`, `crtMatrix`, `pixelate`, `vectorFieldWarp`, `pixelStretch`, `neonGlow`, `edgeDetect`, `doubleExposure`, ★ `filmStock`, `fastBlur`, `gridLines`, `strip`, `ascii`, `objectDither`, `objectIsolines`, `objectWindow`, `objectSlitScan`, `objectCurtain`, `objectGrid`, `objectContour`, `objectNodes`, `objectLinks`, `objectFacets`, `objectMeasure`
|
|
129
|
+
**Overlay effects** (`effects`): `glow`, ★ `bloom`, `auraBlur`, `gradientBeam`, ★ `gradientSweep`, `gradientGlow`, `fractalNoise`, ★ `rgbSplit`, `glitch`, `scanlines`, `flashBlink`, `vhs`, `fisheye`, `opticsCompensation`, `vignette`, ★ `echo`, `timeshift`, `radialBlur`, ★ `radialFastBlur`, `sharpen`, `mirror`, `waveWarp`, `warpStyles`, `shockwave`, `waveLines`, `waveRipple`, `fill`, `shapeRulers`, `copyColor`, `curves`, `turbulentDisplace`, `alphaChoker`, `extract`, ★ `colorama`, `posterize`, ★ `halftone`, ★ `fastCameraWiggle`, ★ `lightRays`, `longShadow`, `outlineBands`, `kaleidoscope`, `crtMatrix`, `pixelate`, `vectorFieldWarp`, `pixelStretch`, `neonGlow`, `edgeDetect`, `doubleExposure`, ★ `filmStock`, `fastBlur`, `gridLines`, `strip`, `ascii`, `objectDither`, `objectIsolines`, `objectWindow`, `objectSlitScan`, `objectCurtain`, `objectGrid`, `objectContour`, `objectNodes`, `objectLinks`, `objectFacets`, `objectMeasure`
|
|
130
130
|
|
|
131
131
|
**Layer effects** (`effects`): `mockupFrame`, ★ `runningGlow`, `depthMap`, `depth3d`, `depthScan`, `fresnelRim`, ★ `motionBlur`, `posterizeTime`, ★ `motionTrail`, `autoFill`, ★ `repetile`, `regionDistort`, `bend`, `cornerPin`, `meshWarp`, `bezierWarp`, `rig`, ★ `droste`, `pryzm`, ★ `glass`, `chromaKey`, `layerMask`
|
|
132
132
|
|
|
@@ -34,10 +34,13 @@ and check every version against them.
|
|
|
34
34
|
|
|
35
35
|
## Easing by intent
|
|
36
36
|
|
|
37
|
-
- Entrances: `AE
|
|
37
|
+
- Entrances: `AE In (arrive)`, `Expo Out` or `Power` (fast start, soft landing); UI panels and drawers: `Apple Out`.
|
|
38
|
+
Camera and big moves: `AE Smooth`.
|
|
39
|
+
- Scene changes on the beat, a logo hit, a screen swipe: `Punch` (slow wind-up, hard hit, long tail).
|
|
38
40
|
- A layer that passes through (in, glide, out): `Smooth Glide` with the `glide` expression — the Glide keyframe
|
|
39
41
|
presets build it (video-keyframes.md).
|
|
40
|
-
- Playful arrivals: `Back Out` or `Overshoot
|
|
42
|
+
- Playful arrivals: `Back Out` or `Overshoot`; a real spring: the `spring` expression (Snappy for buttons, icons and
|
|
43
|
+
pop-ins, Gentle for mascots, big cards and the camera). Exits: `Ease In` or `AE Out (leave)`.
|
|
41
44
|
- `Linear` only for constant motion: tickers, rotation, progress along a path.
|
|
42
45
|
|
|
43
46
|
## Text animation
|
|
@@ -149,7 +149,7 @@ missing ones take the default shown, and out-of-range values are clamped on load
|
|
|
149
149
|
"revealDuration": 0.6, // seconds, for ONE cell
|
|
150
150
|
"revealStagger": 0.05, // seconds between cells (negative runs the wave backwards)
|
|
151
151
|
"revealStaggerBy": "index", // index | ring | distance | random
|
|
152
|
-
"revealEase": "
|
|
152
|
+
"revealEase": "Ease Out",
|
|
153
153
|
"revealOut": false, // cells leave again before the layer ends, in the same order
|
|
154
154
|
|
|
155
155
|
// ── layout slots + morph (Grid Morph) ──
|
|
@@ -168,7 +168,7 @@ missing ones take the default shown, and out-of-range values are clamped on load
|
|
|
168
168
|
"layoutMix": 0, // 0…layouts.length-1 — keyframe `gr:layoutMix` to morph; integer = exactly that slot (single layout evaluated); a Hold key hard-cuts
|
|
169
169
|
"morphStagger": 0.35, // 0–0.9 — spreads the move across cell ranks (0 = all cells slide together)
|
|
170
170
|
"morphStaggerBy": "index", // index | ring | distance | random — ranked on the layout being LEFT
|
|
171
|
-
"morphEase": "
|
|
171
|
+
"morphEase": "Smooth",// per-cell ramp (TransitionEasing name)
|
|
172
172
|
"morphArc": 60, // px — bulges each cell's travel outward mid-move (negative implodes); exactly zero at both endpoints
|
|
173
173
|
"morphSpin": 0 // whole turns added over the blend; integers land back on themselves
|
|
174
174
|
}
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
|
|
20
20
|
Every timeline item can animate its visual properties over the clip's duration. Each property gets its **own independent track** of keys under `propertyKeyframes` — an opacity fade on a different rhythm than a slow zoom, a rotation eased with a bounce while the scale stays smooth, etc. Tracks are always separate — there is no merged, all-properties-per-key form.
|
|
21
21
|
|
|
22
|
-
Positions are always **0–100, percent of the clip's played duration** (not seconds). `value` is stored as a **string**. Easing values come from `GET /api/video-editor/capabilities` → `easings.keyframe.values` (e.g. `Linear`, `Smooth`, `Ease In`, `Ease Out`, `AE In`, `AE Smooth`, `AE Out`, `
|
|
22
|
+
Positions are always **0–100, percent of the clip's played duration** (not seconds). `value` is stored as a **string**. Easing values come from `GET /api/video-editor/capabilities` → `easings.keyframe.values` (e.g. `Linear`, `Smooth`, `Ease In`, `Ease Out`, `AE In (arrive)`, `AE Smooth`, `AE Out (leave)`, `Expo Out`, `Power`, `Punch`, `Back Smooth`, `Bounce Out`, `Elastic`, …); an easing set on a key shapes the segment **after** that key. The `AE …` values are the After Effects-style bezier curves shared with MotionFast (`AE Smooth` is the classic slow-start/soft-stop AE feel — a good default for cinematic moves); AE names a curve by the side of the key, so `AE In (arrive)` starts fast and brakes into the key and `AE Out (leave)` starts slow and speeds away. Three more curves for decisive moves: **`Power`** (a hard decelerate, `cubic-bezier(0.23, 1, 0.32, 1)` — enters, landings), **`Punch`** (`cubic-bezier(0.7, 0, 0.1, 1)` — slow wind-up, hard hit, long tail: scene changes on the beat, a logo hit, a screen swipe) and **`Apple Out`** (`cubic-bezier(0.32, 0.72, 0, 1)` — full speed at once, then a long soft stop: UI panels, drawers, a camera landing). Old names still load and are mapped to the curve that replaced them (`easings.keyframe.retired`: `Power2 Out` → `Ease Out`, `Power3 Out` → `Cubic Out`, `Power4 Out` → `Power`, `Circ Out` → `Slow Down`, `Cubic Smooth` → `Natural` …); write the current names. Every easing still comes to a dead stop on its key. For a spring that overshoots and settles in real seconds, put the **`spring`** expression type on the track (`propertyKeyframeFx.<track> = {"type":"spring","params":{"amp":100,"freq":1.6,"damping":0.55}}`, see `spring` under [Track expressions](video-keyframes.md#track-expressions-propertykeyframefx)). For more live energy — a move that lands soft and keeps drifting on, a shot that never sits still between keys — add the `glide` expression type on top of the track (`propertyKeyframeFx.<track> = {"type":"glide","params":{"fast":0.1,"slow":1,"weight":40,"delay":0}}`, see **Glide** under [Track expressions](video-keyframes.md#track-expressions-propertykeyframefx)). Two owner curves sit right after `Smooth`: **`Smooth Glide`** (`cubic-bezier(0.2111, 0.7721, 0.8541, 0.112)` — arrives fast, glides slowly through the middle, leaves fast) and **`Glide Easing Stop`** (`cubic-bezier(0, 0.9125, 1, -0.0338)` — jumps in, all but stops, jumps out). **In and Out pass (the Glide presets):** one track, `0 %` → off-frame on the entry side (`xPercent`/`yPercent` ±100) eased `Smooth Glide`, last key at **`80 %`** → ∓150 (`Linear`), plus `propertyKeyframeFx.<track> = {"type":"glide","params":{"fast":0.1,"slow":0.6,"weight":25,"delay":0}}` — the glide tail lags in seconds, so ±100 → ∓100 at 100 % would still be on screen at the layer's end; these keys make it leave (−130…−145 % over 1.5–4 s layers) with the slow middle near the centre. Five expressive curves from the MotionFast template catalogue are also available: `Natural` (punchy ease-in-out), `Slow Down` (pure decelerate), `Overshoot` (shoots past the target, settles slowly), `Impulse` (anticipation dip backwards before launching), and `Swing` (wind-up, then a springy arrival) — use these to reproduce classic template motion on any layer. A **single-key track holds its value constant** for the whole clip. Transform origin is one item-level field, `keyframeTransformOrigin` (`"center"`, `"top"`, `"bottom"`, `"left"`, `"right"`, a corner such as `"bottom left"`, or `"x% y%"`): the point every rotation (static and keyed, 2D and 3D) and the keyed scale turn about, while `panX`/`panY`/`panZ` stay the layer's resting centre — see [Turning a flat layer in 3D](video-3d.md#flat-layers-in-the-3d-scene--itemshadowplate).
|
|
23
23
|
|
|
24
|
-
**The easing catalogue.** `GET /api/video-editor/capabilities` → `easings` carries both vocabularies with the actual curve behind every name, so a look can be matched or carried into another tool without guessing. `easings.keyframe` covers keyframe and transition easings: `values` (all of them), `transitionValues` (the subset a transition accepts — `Custom` and `Hold` need per-key data and are rejected there), and `curves[]`. `easings.motionTemplate` covers the camelCase names a template's ease field takes (`aeSmooth`, `power2`, …). In `curves[]`, `kind` says which field IS the curve — `bezier` → `cubicBezier` `[x1,y1,x2,y2]` plus a ready-to-paste `css`, `sampled` → `samples`, the curve at t = 0, 0.01 … 1 (values past 0..1 are real overshoot; as CSS that is `linear(<samples>)`). `gsap` names the ease that plays, and `keyframeEquivalent` / `motionTemplateEquivalent` link the same curve across the two vocabularies — only where the curves genuinely match, so treat a missing link as "these are different curves that happen to share a name" (template `smooth` is not keyframe `Smooth`; template `power2` is keyframe `Ease Out`). A `sampled` entry's `cubicBezier` (when marked `bezierIsApproximate`) is only the closest cubic — `bezierMaxError` says how far off, up to ~0.
|
|
24
|
+
**The easing catalogue.** `GET /api/video-editor/capabilities` → `easings` carries both vocabularies with the actual curve behind every name, so a look can be matched or carried into another tool without guessing. `easings.keyframe` covers keyframe and transition easings: `values` (all of them), `transitionValues` (the subset a transition accepts — `Custom` and `Hold` need per-key data and are rejected there), `retired` (old name → the value that replaced it; still accepted on load and by the API) and `curves[]`. `easings.motionTemplate` covers the camelCase names a template's ease field takes (`aeSmooth`, `power2`, …). In `curves[]`, `kind` says which field IS the curve — `bezier` → `cubicBezier` `[x1,y1,x2,y2]` plus a ready-to-paste `css`, `sampled` → `samples`, the curve at t = 0, 0.01 … 1 (values past 0..1 are real overshoot; as CSS that is `linear(<samples>)`). `gsap` names the ease that plays, and `keyframeEquivalent` / `motionTemplateEquivalent` link the same curve across the two vocabularies — only where the curves genuinely match, so treat a missing link as "these are different curves that happen to share a name" (template `smooth` is not keyframe `Smooth`; template `power2` is keyframe `Ease Out`). A `sampled` entry's `cubicBezier` (when marked `bezierIsApproximate`) is only the closest cubic — `bezierMaxError` says how far off, up to ~0.13 for `Expo Smooth`; match against the samples, not the handles. Two easings carry no curve: `Custom` reads the key's own `bezier: [x1,y1,x2,y2]` (write both together or it falls back to Smooth), and `Hold` steps to the next key.
|
|
25
25
|
|
|
26
26
|
```json
|
|
27
27
|
{
|
|
@@ -78,9 +78,10 @@ An AE-style expression layered on top of a track's keyframed value. Stored per t
|
|
|
78
78
|
}
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
`elastic` and `
|
|
81
|
+
`elastic`, `bounce` and `spring` **reshape the move itself** — they are not rings appended after a key. Each keyframe transition is treated as a step of size `value[i] − value[i−1]` that starts at the previous key, so the layer launches there, overshoots the target and settles into it as **one continuous motion**. Consequences worth knowing: the key's own `easing` is superseded on a track carrying one of these (use `amp` to mix back toward it), and it works on the commonest track of all — two keys at 0 and 100 — where a post-key ring would have nowhere to play. `elastic` and `bounce` are normalized to each segment's own duration (the shape is identical for a 0.3s and a 3s move); `spring` runs in seconds instead.
|
|
82
82
|
|
|
83
83
|
- **`elastic`** (`amp` % strength 0–300, `freq` wobbles **across the move** 0.3–5, `decay` 0.5–15) — launches, crosses the target at `1/(4·freq)` of the move, overshoots by ≈`e^(−decay/(2·freq))`, then wobbles in. Defaults (100/1.1/5) give a ~13% overshoot that has settled to <1% by the key. A leftover wobble carries into the next segment as follow-through. Lower `freq` for a soft landing with a single late overshoot; raise it for a fast arrival with several wobbles.
|
|
84
|
+
- **`spring`** (`amp` % strength 0–300, `freq` 0.1–10 Hz, `damping` ratio 0.05–1) — a real damped spring in **seconds**, released at rest from the key before: `x = a + (b−a)·(1 − e^(−ζωt)·(cos ω_d t + ζω/ω_d·sin ω_d t))`, `ω = 2π·freq`, `ω_d = ω·√(1−ζ²)`, `t` = seconds since the move's first key. It peaks at `1 + e^(−ζπ/√(1−ζ²))` of the step and settles in ≈ `4/(ω·ζ)` s whatever the gap to the next key, so a short move and a long one ring at the same rate (Elastic stretches instead); the move's END key only says when the next step starts. A ring not settled carries into the next step. Presets (`keyframeExpressions.types[].presets`, they set `freq` + `damping` only): `snappy` 1.6 Hz / 0.55 — ~13 % overshoot, settled in 0.7 s: buttons, icons, pop-ins (the defaults); `gentle` 1 Hz / 0.8 — 1.5 % overshoot: mascots, big cards, the camera. `damping` 1 never overshoots. Leave each step ~1 s before the next key so the ring has settled.
|
|
84
85
|
- **`bounce`** (`amp` % strength, `elasticity` bounciness 5–80%, `bounces` 1–10) — falls onto the target and rebounds back the way it came in decaying hops. Self-normalizing: the fall plus every hop are scaled to fit the move exactly, so it always settles **on** the key and needs no gravity or hop-duration knob. Higher bounciness spends more of the move hopping (so it lands earlier); it never passes the target.
|
|
85
86
|
- **`wiggle`** (`amp` in the property's own units, `freq` Hz) — deterministic smooth jitter **added around** the keyed value across the whole clip (this one is additive and leaves the base motion intact), seeded per item+track so copies don't move in sync. A single-key (constant) track plus wiggle is the cheapest "handheld"/idle-motion recipe.
|
|
86
87
|
- **`glide`** (`fast` response 0.01–3 s, `slow` tail length 0.05–8 s, `weight` tail share 0–100 %, `delay` tail delay 0–3 s) — **softens** the keyed motion (its easing included): a move lands soft and keeps creeping on in the direction it travelled, never past the key and never back. Presets (also in `keyframeExpressions.types[].presets`): `soft` 0.1/0.6/25/0 (the defaults), `floaty` 0.1/1/40/0, `trailing` 0.1/0.45/25/0.1, `endless` 0.1/2/14/0. Same filter as `glide()` in a custom expression. See **Glide** below.
|
|
@@ -84,7 +84,7 @@ in the last frames.
|
|
|
84
84
|
| [Center Burst](#center-burst) | The middle words burst out first and the others follow, wobbling into place; at the end they shrink away from the outside in | words | each word's centre | Elastic · Back In |
|
|
85
85
|
| [Pendulum](#pendulum) | Words hang from their top edge and swing in like a pendulum until they settle; at the end they swing away | words | each word's centre | Elastic · Anticipate |
|
|
86
86
|
| [Spin Pop](#spin-pop) | Each word spins a full turn in place as it grows in; at the end each spins back out | words | each word's centre | Back Out · Back In |
|
|
87
|
-
| [Domino](#domino) | Words stand up on their bottom-left corner and drop flat with a bounce, one after another; at the end they fall over | words | each word's bottom-left corner | Bounce Out ·
|
|
87
|
+
| [Domino](#domino) | Words stand up on their bottom-left corner and drop flat with a bounce, one after another; at the end they fall over | words | each word's bottom-left corner | Bounce Out · Ease In |
|
|
88
88
|
| [Flip Pop](#flip-pop) | Words flip up into view in 3D, past flat and back; at the end they tip back and flip away | words | each word's centre | Overshoot · Anticipate |
|
|
89
89
|
| [Card Turn](#card-turn) | Words turn to face you like cards, one by one, overshooting the turn; at the end they turn away | words | each word's centre | Overshoot · Anticipate |
|
|
90
90
|
| [Slam Zoom](#slam-zoom) | Words slam down from huge, punch past their size and settle; at the end they fly back at the camera | words | each word's centre | Overshoot · Expo In |
|
|
@@ -93,7 +93,7 @@ in the last frames.
|
|
|
93
93
|
| [Whip](#whip) | Words whip in from the left leaning into the move, snap past and settle; at the end they lean back and whip off to the right | words | each word's centre | Overshoot · Anticipate |
|
|
94
94
|
| [Rubber Letters](#rubber-letters) | Letters spring out of thin slivers and wobble like rubber; at the end they stretch tall and squash flat | letters | each letter's centre | Elastic · Anticipate |
|
|
95
95
|
| [Pop Letters](#pop-letters) | Letters pop up in random order, each with a little twist; at the end they swell and pop away at random | letters | each letter's centre | Overshoot · Anticipate |
|
|
96
|
-
| [Drop Swing](#drop-swing) | Words drop in tilted from above and bounce as they land; at the end they fall out of the frame | words | each word's centre | Bounce Out ·
|
|
96
|
+
| [Drop Swing](#drop-swing) | Words drop in tilted from above and bounce as they land; at the end they fall out of the frame | words | each word's centre | Bounce Out · Ease In |
|
|
97
97
|
| [Coin Spin](#coin-spin) | Letters spin in like coins, one after another, and rock to a stop; at the end they spin away | letters | each letter's centre | Overshoot · Anticipate |
|
|
98
98
|
| [Converge](#converge) | Words shrink down from far bigger, the outer ones first, and settle; at the end they burst outward | words | each word's centre | Expo Out · Expo In |
|
|
99
99
|
| [Roll In](#roll-in) | Letters roll in from the right like wheels and rock back into place; at the end they roll off to the left | letters | each letter's centre | Overshoot · Back In |
|
|
@@ -215,7 +215,7 @@ Words stand up on their bottom-left corner and drop flat with a bounce, one afte
|
|
|
215
215
|
"range": {"basedOn": "words", "drive": "time", "animate": "in", "around": "word", "stagger": 0.14, "duration": 1, "curve": "Bounce Out"},
|
|
216
216
|
"effects": [{"pid": "p1", "type": "rotation", "angle": -90}, {"pid": "p2", "type": "opacity", "opacity": 0}] },
|
|
217
217
|
{ "aid": "a2", "name": "Fall out",
|
|
218
|
-
"range": {"basedOn": "words", "drive": "time", "animate": "out", "around": "word", "stagger": 0.08, "duration": 0.6, "curve": "
|
|
218
|
+
"range": {"basedOn": "words", "drive": "time", "animate": "out", "around": "word", "stagger": 0.08, "duration": 0.6, "curve": "Ease In"},
|
|
219
219
|
"effects": [{"pid": "p3", "type": "rotation", "angle": 90}, {"pid": "p4", "type": "opacity", "opacity": 0}] }
|
|
220
220
|
],
|
|
221
221
|
"textAnimatorPivotX": -100,
|
|
@@ -371,7 +371,7 @@ Words drop in tilted from above and bounce as they land; at the end they fall ou
|
|
|
371
371
|
"range": {"basedOn": "words", "drive": "time", "animate": "in", "around": "word", "stagger": 0.08, "duration": 0.9, "curve": "Bounce Out"},
|
|
372
372
|
"effects": [{"pid": "p1", "type": "position", "x": 0, "y": -120}, {"pid": "p2", "type": "rotation", "angle": 25}, {"pid": "p3", "type": "opacity", "opacity": 0}] },
|
|
373
373
|
{ "aid": "a2", "name": "Fall out",
|
|
374
|
-
"range": {"basedOn": "words", "drive": "time", "animate": "out", "around": "word", "stagger": 0.04, "duration": 0.5, "curve": "
|
|
374
|
+
"range": {"basedOn": "words", "drive": "time", "animate": "out", "around": "word", "stagger": 0.04, "duration": 0.5, "curve": "Ease In"},
|
|
375
375
|
"effects": [{"pid": "p4", "type": "position", "x": 0, "y": 120}, {"pid": "p5", "type": "rotation", "angle": -25}, {"pid": "p6", "type": "opacity", "opacity": 0}] }
|
|
376
376
|
]
|
|
377
377
|
}
|
|
@@ -87,7 +87,7 @@ Type on Shape has no preferred preset: pick by the shape the text needs.
|
|
|
87
87
|
|
|
88
88
|
```json
|
|
89
89
|
{ "aid": "a9", "name": "Out",
|
|
90
|
-
"range": {"drive": "time", "animate": "out", "basedOn": "words", "stagger": 0.04, "duration": 0.3, "curve": "
|
|
90
|
+
"range": {"drive": "time", "animate": "out", "basedOn": "words", "stagger": 0.04, "duration": 0.3, "curve": "Ease In"},
|
|
91
91
|
"effects": [{"pid": "p19", "type": "opacity", "opacity": 0}] }
|
|
92
92
|
```
|
|
93
93
|
|
|
@@ -162,20 +162,20 @@ Letters type in as the word glides left under a chasing blue band and settles, t
|
|
|
162
162
|
"range": {"basedOn": "charsNoSpace", "around": "all"},
|
|
163
163
|
"effects": [{"pid": "p3", "type": "position", "x": 250, "y": 0}] },
|
|
164
164
|
{ "aid": "a4", "name": "Glide out",
|
|
165
|
-
"range": {"basedOn": "charsNoSpace", "drive": "time", "animate": "out", "around": "all", "stagger": 0, "duration": 0.5, "curve": "
|
|
165
|
+
"range": {"basedOn": "charsNoSpace", "drive": "time", "animate": "out", "around": "all", "stagger": 0, "duration": 0.5, "curve": "Ease In"},
|
|
166
166
|
"effects": [{"pid": "p4", "type": "position", "x": -150, "y": 0}, {"pid": "p5", "type": "opacity", "opacity": 0}] }
|
|
167
167
|
],
|
|
168
168
|
"propertyKeyframes": {
|
|
169
169
|
"txa:a1:start": [
|
|
170
|
-
{ "position": 0, "value": "0", "easing": "AE In" }, // 0 s
|
|
170
|
+
{ "position": 0, "value": "0", "easing": "AE In (arrive)" }, // 0 s
|
|
171
171
|
{ "position": 20, "value": "100", "easing": "Smooth" } // 1 s
|
|
172
172
|
],
|
|
173
173
|
"txa:a2:offset": [
|
|
174
|
-
{ "position": 6, "value": "-58", "easing": "
|
|
174
|
+
{ "position": 6, "value": "-58", "easing": "Sine Out" }, // 0.3 s
|
|
175
175
|
{ "position": 26, "value": "101", "easing": "Smooth" } // 1.3 s
|
|
176
176
|
],
|
|
177
177
|
"txa:a3:amount": [
|
|
178
|
-
{ "position": 0, "value": "100", "easing": "AE In" }, // 0 s
|
|
178
|
+
{ "position": 0, "value": "100", "easing": "AE In (arrive)" }, // 0 s
|
|
179
179
|
{ "position": 20, "value": "0", "easing": "Smooth" } // 1 s
|
|
180
180
|
]
|
|
181
181
|
}
|
|
@@ -199,16 +199,16 @@ Letters type in under a chasing blue band as the word keeps gliding through the
|
|
|
199
199
|
"range": {"basedOn": "charsNoSpace", "around": "all"},
|
|
200
200
|
"effects": [{"pid": "p3", "type": "position", "x": 250, "y": 0}] },
|
|
201
201
|
{ "aid": "a4", "name": "Glide out",
|
|
202
|
-
"range": {"basedOn": "charsNoSpace", "drive": "time", "animate": "out", "around": "all", "stagger": 0, "duration": 0.5, "curve": "
|
|
202
|
+
"range": {"basedOn": "charsNoSpace", "drive": "time", "animate": "out", "around": "all", "stagger": 0, "duration": 0.5, "curve": "Ease In"},
|
|
203
203
|
"effects": [{"pid": "p4", "type": "position", "x": -150, "y": 0}, {"pid": "p5", "type": "opacity", "opacity": 0}] }
|
|
204
204
|
],
|
|
205
205
|
"propertyKeyframes": {
|
|
206
206
|
"txa:a1:start": [
|
|
207
|
-
{ "position": 0, "value": "0", "easing": "AE In" }, // 0 s
|
|
207
|
+
{ "position": 0, "value": "0", "easing": "AE In (arrive)" }, // 0 s
|
|
208
208
|
{ "position": 18.6, "value": "100", "easing": "Smooth" } // 0.93 s
|
|
209
209
|
],
|
|
210
210
|
"txa:a2:offset": [
|
|
211
|
-
{ "position": 2.8, "value": "-58", "easing": "
|
|
211
|
+
{ "position": 2.8, "value": "-58", "easing": "Sine Out" }, // 0.14 s
|
|
212
212
|
{ "position": 22.6, "value": "101", "easing": "Smooth" } // 1.13 s
|
|
213
213
|
],
|
|
214
214
|
"txa:a3:amount": [
|
|
@@ -227,13 +227,13 @@ Words spring in out of a hot green glow and overshoot into place as the line rec
|
|
|
227
227
|
{
|
|
228
228
|
"textAnimators": [
|
|
229
229
|
{ "aid": "a1", "name": "Recenter",
|
|
230
|
-
"range": {"basedOn": "words", "drive": "time", "animate": "in", "around": "all", "stagger": 0, "duration": 1.8, "curve": "
|
|
230
|
+
"range": {"basedOn": "words", "drive": "time", "animate": "in", "around": "all", "stagger": 0, "duration": 1.8, "curve": "Cubic Out"},
|
|
231
231
|
"effects": [{"pid": "p1", "type": "position", "x": 462.96, "y": 0}] },
|
|
232
232
|
{ "aid": "a2", "name": "Spring in",
|
|
233
233
|
"range": {"basedOn": "words", "drive": "time", "animate": "in", "around": "word", "stagger": 0.15, "duration": 1.1, "curve": "Overshoot"},
|
|
234
234
|
"effects": [{"pid": "p2", "type": "position", "x": 129.63, "y": 157.41}, {"pid": "p3", "type": "scale", "scale": 78}] },
|
|
235
235
|
{ "aid": "a3", "name": "Focus in",
|
|
236
|
-
"range": {"basedOn": "words", "drive": "time", "animate": "in", "around": "auto", "stagger": 0.15, "duration": 0.38, "curve": "
|
|
236
|
+
"range": {"basedOn": "words", "drive": "time", "animate": "in", "around": "auto", "stagger": 0.15, "duration": 0.38, "curve": "Ease Out"},
|
|
237
237
|
"effects": [{"pid": "p4", "type": "opacity", "opacity": 0}, {"pid": "p5", "type": "blur", "amount": 25.93}] },
|
|
238
238
|
{ "aid": "a4", "name": "Hot glow",
|
|
239
239
|
"range": {"basedOn": "words", "drive": "time", "animate": "in", "around": "auto", "stagger": 0.15, "duration": 0.65, "curve": "Sine Smooth"},
|
|
@@ -265,16 +265,16 @@ The same typing and band, but the word glides through the whole layer and all bu
|
|
|
265
265
|
"range": {"basedOn": "charsNoSpace", "around": "all"},
|
|
266
266
|
"effects": [{"pid": "p3", "type": "position", "x": 250, "y": 0}] },
|
|
267
267
|
{ "aid": "a4", "name": "Glide out",
|
|
268
|
-
"range": {"basedOn": "charsNoSpace", "drive": "time", "animate": "out", "around": "all", "stagger": 0, "duration": 0.5, "curve": "
|
|
268
|
+
"range": {"basedOn": "charsNoSpace", "drive": "time", "animate": "out", "around": "all", "stagger": 0, "duration": 0.5, "curve": "Ease In"},
|
|
269
269
|
"effects": [{"pid": "p4", "type": "position", "x": -150, "y": 0}, {"pid": "p5", "type": "opacity", "opacity": 0}] }
|
|
270
270
|
],
|
|
271
271
|
"propertyKeyframes": {
|
|
272
272
|
"txa:a1:start": [
|
|
273
|
-
{ "position": 0, "value": "0", "easing": "AE In" }, // 0 s
|
|
273
|
+
{ "position": 0, "value": "0", "easing": "AE In (arrive)" }, // 0 s
|
|
274
274
|
{ "position": 18.6, "value": "100", "easing": "Smooth" } // 0.93 s
|
|
275
275
|
],
|
|
276
276
|
"txa:a2:offset": [
|
|
277
|
-
{ "position": 2.8, "value": "-58", "easing": "
|
|
277
|
+
{ "position": 2.8, "value": "-58", "easing": "Sine Out" }, // 0.14 s
|
|
278
278
|
{ "position": 22.6, "value": "101", "easing": "Smooth" } // 1.13 s
|
|
279
279
|
],
|
|
280
280
|
"txa:a3:amount": [
|
|
@@ -1039,7 +1039,7 @@ A box sits under each word while it is spoken, dark text on top. Plays: while ea
|
|
|
1039
1039
|
{
|
|
1040
1040
|
"textAnimators": [
|
|
1041
1041
|
{ "aid": "a1", "name": "Spoken box",
|
|
1042
|
-
"range": {"basedOn": "words", "drive": "voice", "animate": "active", "duration": 0.08, "curve": "
|
|
1042
|
+
"range": {"basedOn": "words", "drive": "voice", "animate": "active", "duration": 0.08, "curve": "Ease Out", "fadeOut": 0.08},
|
|
1043
1043
|
"effects": [{"pid": "p1", "type": "box", "color": "#33efab", "padX": 12, "padY": 4, "radius": 14, "grow": false}, {"pid": "p2", "type": "fill", "color": "#0b0d0c"}] }
|
|
1044
1044
|
]
|
|
1045
1045
|
}
|
|
@@ -1109,7 +1109,7 @@ Words wait dimmed and light up as they are said. Plays: as each word is spoken.
|
|
|
1109
1109
|
{
|
|
1110
1110
|
"textAnimators": [
|
|
1111
1111
|
{ "aid": "a1", "name": "Not spoken yet",
|
|
1112
|
-
"range": {"basedOn": "words", "drive": "voice", "animate": "in", "duration": 0.2, "curve": "
|
|
1112
|
+
"range": {"basedOn": "words", "drive": "voice", "animate": "in", "duration": 0.2, "curve": "Ease Out"},
|
|
1113
1113
|
"effects": [{"pid": "p1", "type": "opacity", "opacity": 30}] }
|
|
1114
1114
|
]
|
|
1115
1115
|
}
|
|
@@ -1137,7 +1137,7 @@ Words rise softly out of a blur as they are spoken. Plays: as each word is spoke
|
|
|
1137
1137
|
{
|
|
1138
1138
|
"textAnimators": [
|
|
1139
1139
|
{ "aid": "a1", "name": "Rise",
|
|
1140
|
-
"range": {"basedOn": "words", "drive": "voice", "animate": "in", "duration": 0.45, "curve": "
|
|
1140
|
+
"range": {"basedOn": "words", "drive": "voice", "animate": "in", "duration": 0.45, "curve": "Cubic Out"},
|
|
1141
1141
|
"effects": [{"pid": "p1", "type": "position", "x": 0, "y": 45}, {"pid": "p2", "type": "blur", "amount": 8}, {"pid": "p3", "type": "opacity", "opacity": 0}] }
|
|
1142
1142
|
]
|
|
1143
1143
|
}
|
|
@@ -150,9 +150,9 @@ Orders {{{COUNTER:0-2,480; style=roll; duration=2.5; easing=expo_out}}} in {{{TI
|
|
|
150
150
|
|
|
151
151
|
| Type | Options (defaults) |
|
|
152
152
|
|---|---|
|
|
153
|
-
| COUNTER | `style` odometer\|roll\|count (odometer) · `start` s (0) · `duration` s (1.8) · `easing` a TransitionEasing key in lowercase, e.g. `
|
|
153
|
+
| COUNTER | `style` odometer\|roll\|count (odometer) · `start` s (0) · `duration` s (1.8) · `easing` a TransitionEasing key in lowercase, e.g. `cubic_out` (cubic_out) · `width` fixed\|fit (fixed) · `digits` tabular\|natural, Count only (tabular) · `turns` 0–10 (3) · `lands` left\|right\|together (left) · `cascade` 0–90 % (45) · `direction` auto\|up\|down (auto) · `blur` 0–100 % (35) · `kf` a track id |
|
|
154
154
|
| TIMER | the same keys; defaults are a real clock: `style` count, `duration` = the timer's own span (05:00 → 300 s), `easing` linear |
|
|
155
|
-
| CYCLE | `style` roll\|fade\|blur (roll) · `start` (0) · `hold` s per word (1.2) · `duration` transition s (0.45) · `easing` (
|
|
155
|
+
| CYCLE | `style` roll\|fade\|blur (roll) · `start` (0) · `hold` s per word (1.2) · `duration` transition s (0.45) · `easing` (cubic_out) · `width` fit\|fixed (fit) · `direction` up\|down, roll only (up) · `loop` on\|off (on) |
|
|
156
156
|
| SCRAMBLE | `start` (0) · `duration` (1.2) · `chars` symbols\|letters\|digits\|binary\|blocks (symbols) · `order` ltr\|rtl\|random (ltr) · `flicker` glyph changes/s (18) |
|
|
157
157
|
| TIMECODE / FRAME | no options — `clip` and the format are the token body (`{{{TIMECODE:clip mm:ss}}}`) |
|
|
158
158
|
|
|
@@ -221,7 +221,7 @@ Rules the sanitizer enforces (anything else is dropped or clamped on load): `aid
|
|
|
221
221
|
| `delay` | −60…600 s (0) | In: after the layer starts. Out: before it ends. Voice: after the word is spoken (negative = before). |
|
|
222
222
|
| `stagger` | 0…10 s (0.06) | Time: between one unit's turn and the next. |
|
|
223
223
|
| `duration` | 0…20 s (0.6) | How long each unit takes (0 = instant). For `active`/`stay` it is the fade-in. |
|
|
224
|
-
| `curve` | the app's easing names (`Ease Out`) | Each unit's own easing: `Linear`, `Ease In/Out`, `Smooth`, `
|
|
224
|
+
| `curve` | the app's easing names (`Ease Out`) | Each unit's own easing: `Linear`, `Ease In/Out`, `Smooth`, `Smooth Glide`, `Glide Easing Stop`, `Sine/Expo/Back In/Out/Smooth`, `Cubic In/Out`, `Power`, `Punch`, `Apple Out`, `Bounce Out`, `Elastic`, `Overshoot`, `Smooth Overshoot`, `Impulse`, `Swing`, `Anticipate`, `Natural`, `Slow Down`, `AE In (arrive)`, `AE Smooth`, `AE Out (leave)` (a retired name such as `Power2 Smooth` loads as its replacement). Back, Bounce, Elastic and the Overshoots land each unit past its rest and settle (transforms follow the overshoot, colours clamp). `Anticipate` is an exit: the unit winds back the other way (to −0.38 of the move at 58 %), then snaps through in the last frames. `Custom` plays `bezier`. |
|
|
225
225
|
| `bezier` | `[x1, y1, x2, y2]` or null (null) | The `Custom` curve's handles, the same shape as a keyframe's `bezier` (x 0…1, y −3…4; past 0…1 = overshoot). Write it together with `"curve": "Custom"`: a `Custom` without it plays `Ease Out`, and any named `curve` drops it. |
|
|
226
226
|
| `hold` | 0…600 s (0) | `active`: how long a unit stays lit; 0 = until the next unit's turn (voice: until the next word starts). |
|
|
227
227
|
| `fadeOut` | 0…20 s (0) | `active`: fade back down after `hold`. |
|
|
@@ -297,16 +297,16 @@ Worked examples (spread onto a text item; durations assume a 4 s layer):
|
|
|
297
297
|
|
|
298
298
|
// Fade Up (Time): words rise in 0.06 s apart, and leave upward at the end.
|
|
299
299
|
"textAnimators": [
|
|
300
|
-
{ "aid": "a1", "name": "In", "range": { "drive": "time", "animate": "in", "basedOn": "words", "stagger": 0.06, "duration": 0.8, "curve": "
|
|
300
|
+
{ "aid": "a1", "name": "In", "range": { "drive": "time", "animate": "in", "basedOn": "words", "stagger": 0.06, "duration": 0.8, "curve": "Smooth" },
|
|
301
301
|
"effects": [ { "pid": "p1", "type": "position", "x": 0, "y": 50 }, { "pid": "p2", "type": "opacity", "opacity": 0 } ] },
|
|
302
|
-
{ "aid": "a2", "name": "Out", "range": { "drive": "time", "animate": "out", "basedOn": "words", "stagger": 0.06, "duration": 0.7, "curve": "
|
|
302
|
+
{ "aid": "a2", "name": "Out", "range": { "drive": "time", "animate": "out", "basedOn": "words", "stagger": 0.06, "duration": 0.7, "curve": "Smooth" },
|
|
303
303
|
"effects": [ { "pid": "p3", "type": "position", "x": 0, "y": -50 }, { "pid": "p4", "type": "opacity", "opacity": 0 } ] }]
|
|
304
304
|
|
|
305
305
|
// Energetic in and out (Swing Pop and 20 more, each two Time animators): video-text-kinetic.md.
|
|
306
306
|
// Every other app preset (typing reveals, text on shapes, highlights, loops, decoders, voice): video-text-presets.md.
|
|
307
307
|
|
|
308
308
|
// Caption karaoke on the voice (needs textWordTimings): a box sits under each word while it is spoken.
|
|
309
|
-
"textAnimators": [{ "aid": "a1", "name": "Spoken box", "range": { "drive": "voice", "animate": "active", "basedOn": "words", "duration": 0.08, "curve": "
|
|
309
|
+
"textAnimators": [{ "aid": "a1", "name": "Spoken box", "range": { "drive": "voice", "animate": "active", "basedOn": "words", "duration": 0.08, "curve": "Ease Out", "fadeOut": 0.08 },
|
|
310
310
|
"effects": [ { "pid": "p1", "type": "box", "color": "#33efab", "padX": 12, "padY": 4, "radius": 14, "grow": false }, { "pid": "p2", "type": "fill", "color": "#0b0d0c" } ] }]
|
|
311
311
|
|
|
312
312
|
// Letters typed at speaking pace behind a caret (captions).
|
|
@@ -359,9 +359,9 @@ PUT /api/moodboards/{board_id}/video-projects/{project_id}
|
|
|
359
359
|
"textFontWeight": 800, "textAlign": "center",
|
|
360
360
|
"panX": 0, "panY": 35,
|
|
361
361
|
"textAnimators": [
|
|
362
|
-
{ "aid": "a1", "name": "In", "range": { "drive": "time", "animate": "in", "basedOn": "words", "stagger": 0.06, "duration": 0.8, "curve": "
|
|
362
|
+
{ "aid": "a1", "name": "In", "range": { "drive": "time", "animate": "in", "basedOn": "words", "stagger": 0.06, "duration": 0.8, "curve": "Smooth" },
|
|
363
363
|
"effects": [ { "pid": "p1", "type": "position", "x": 0, "y": 50 }, { "pid": "p2", "type": "opacity", "opacity": 0 } ] },
|
|
364
|
-
{ "aid": "a2", "name": "Out", "range": { "drive": "time", "animate": "out", "basedOn": "words", "stagger": 0.06, "duration": 0.7, "curve": "
|
|
364
|
+
{ "aid": "a2", "name": "Out", "range": { "drive": "time", "animate": "out", "basedOn": "words", "stagger": 0.06, "duration": 0.7, "curve": "Smooth" },
|
|
365
365
|
"effects": [ { "pid": "p3", "type": "position", "x": 0, "y": -50 }, { "pid": "p4", "type": "opacity", "opacity": 0 } ] }
|
|
366
366
|
]
|
|
367
367
|
}
|