@pixerate/editor 0.67.0 → 0.67.1
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/dist/animation-editor/index.cjs +8 -7
- package/dist/animation-editor/index.cjs.map +1 -1
- package/dist/animation-editor/index.d.cts +9 -4
- package/dist/animation-editor/index.d.ts +9 -4
- package/dist/animation-editor/index.js +8 -7
- package/dist/animation-editor/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -31,8 +31,8 @@ interface MotionScene {
|
|
|
31
31
|
loop?: AnimationLoopMode;
|
|
32
32
|
/**
|
|
33
33
|
* Plays in answer to the viewer instead of on its own (exported to Flair's player):
|
|
34
|
-
* - `click`:
|
|
35
|
-
* a click plays the
|
|
34
|
+
* - `click`: nothing plays until the viewer clicks; each click plays the next shot, and after the
|
|
35
|
+
* last one a click plays the first again, so a last shot that puts things back makes a toggle.
|
|
36
36
|
* - `hover` / `press`: plays forward while the pointer is over (or down on) it, and back when it leaves.
|
|
37
37
|
* - `scroll`: scrubs through the scene as it scrolls through the viewport.
|
|
38
38
|
* The editor previews it played through; `loop` does not apply.
|
|
@@ -1238,7 +1238,7 @@ interface FlairMotionExport {
|
|
|
1238
1238
|
interface FlairExportOptions {
|
|
1239
1239
|
/**
|
|
1240
1240
|
* Play in answer to the viewer (default: the scene's `trigger`; null for none). With `click`
|
|
1241
|
-
*
|
|
1241
|
+
* shot n is Flair step n + 1: nothing plays until the first click, and each click plays the next shot.
|
|
1242
1242
|
*/
|
|
1243
1243
|
trigger?: MotionTrigger | null;
|
|
1244
1244
|
/** Sampling rate for changes Flair cannot express exactly (default: the scene's `fps`, else 30). */
|
|
@@ -1317,6 +1317,11 @@ interface FlairImportOptions {
|
|
|
1317
1317
|
name?: string;
|
|
1318
1318
|
/** Hold after the last shot, ms (default: the effect's `hold`, else 600). */
|
|
1319
1319
|
hold?: number;
|
|
1320
|
+
/**
|
|
1321
|
+
* The motion plays on click: Flair plays step 0 together with step 1 on the first click, so
|
|
1322
|
+
* both become the first shot (as `toFlairSvgMotion` writes them).
|
|
1323
|
+
*/
|
|
1324
|
+
clickSteps?: boolean;
|
|
1320
1325
|
}
|
|
1321
1326
|
/** A Flair `SvgMotion` as a scene (see the module notes for what carries over). */
|
|
1322
1327
|
declare function fromFlairSvgMotion(input: FlairSvgMotion, options?: FlairImportOptions): FlairImportResult;
|
|
@@ -1956,7 +1961,7 @@ declare function createAnimationEditorToolProvider(controller: AnimationEditorCo
|
|
|
1956
1961
|
* A short authoring guide for a model writing vector animations with the animation editor's
|
|
1957
1962
|
* tools. Static, so it caches well as part of a system prompt.
|
|
1958
1963
|
*/
|
|
1959
|
-
declare const ANIMATION_EDITOR_AGENT_INSTRUCTIONS = "You animate vector artwork. A scene is artwork (vector paths and groups, each with an id) plus shots.\n\nHow it plays\n- Shots play in order. A shot optionally moves the camera, plays its commands, then holds (default 600 ms).\n- Commands in a shot play one after another; give \"with\": \"previous\" to start one together with the command before, \"delay\" to wait, \"stagger\" to offset several targets.\n- Timing comes from the content: each command has a default length (enter 600 ms, move 700 ms, draw follows the path length). Only set \"duration\" to change the pace.\n- Anything that enters later is hidden until it enters. Things that never enter are visible from the start.\n- Every frame is a pure function of time: the same scene always plays the same frames.\n\nCommands\n- enter (fade, pop, grow, slide, draw) and exit (fade, shrink, slide, undraw) bring things in and out.\n- enter also reveals through a clip over the target's box: wipe (behind an edge travelling \"direction\", default right), iris (from the centre; \"shape\": circle or box) and split (from a line through the middle; \"orientation\": horizontal or vertical). exit wipe hides the same way. Reveals need a width and a height: use draw / undraw for a straight line.\n- draw draws strokes on to a fraction; move, rotate, scale and fade change the pose (about the centre); style blends solid colours and stroke width.\n- enter also has zoom (settles from larger) and rise (rises a short way, overshooting a touch); pop and zoom take a starting \"scale\".\n- morph turns a shape into another node's shape (keep the target hidden); match does the same for a whole group, part by part (Smart Animate: draw the end state as a second, hidden group whose parts share names with the first); follow moves along a path node (with \"rotate\", moves made meanwhile turn with the path).\n- Emphasis draws the eye and returns to rest: pulse (swell), shake (side to side, or \"axis\": \"vertical\"), teeter (rock), wave (bob, no settling), wiggle (seeded wander; the same seed wanders the same way) and color-pulse (tint and back).\n- Emphasis stacks on other motion: a shake during a slide shakes as it slides. Give move, rotate or scale \"blend\": \"add\" to stack them too (what they add stays); \"blend\": \"replace\" makes a change take over instead.\n- Any command but enter and exit can \"repeat\" (loop, mirror back and forth, or offset to carry on: rotate by 90, repeat 4 is a full turn); \"duration\" is one cycle.\n- Springs (\"spring-gentle\", \"spring-quick\", \"spring-bouncy\", \"spring-slow\" or { \"type\": \"spring\", \u2026 }) feel physical; leave \"duration\" out and the spring sets it.\n- To time shots to music or a voiceover: set a \"beat\" grid or \"narration\" word timings with set_animation_settings, read them with get_timing_grid, and give a shot \"at\": { \"beat\": n } or { \"word\": i }. The shot before holds until the cue; check_animation warns when a cue is missed.\n- \"steps\": 12 (on a command, or for the whole scene with set_animation_settings) holds poses \"on twos\" for a hand-drawn look. \"geometric\": true on scale or a camera zooms at an even rate.\n- Commands share their names and defaults with Flair's motion primitives (get_animation shows each one's \"flairPrimitive\"), and emphasis, reveals and follows export to Flair exactly.\n- effect tweens a numeric parameter of a live path effect already on the node (twist angle, wiggle time, zig zag size).\n\nWorking method\n1. get_animation to learn the element ids (set_animation_artwork_svg first if there is no artwork: give every element you will animate an id; or import_flair_effect to start from a Flair effect and edit it).\n2. Plan a few shots, each one idea. Add them with insert_shots (add_commands, update_command, move_command and delete_commands refine a shot), or edit_animation to make several edits as one step (dry_run first when unsure).\n3. To hit a length, fit_animation (keep the shots whose pace matters). check_animation and fix every error and warning; render_animation_frame (shot + \"end\") to look at the result; add onion_skin or motion_paths to see the motion in one picture, or get_motion_path for the numbers.\n- For something the viewer plays (a button, a toggle, a step-by-step explainer), set \"trigger\" with set_animation_settings: click plays the next shot on each click (make the last shot
|
|
1964
|
+
declare const ANIMATION_EDITOR_AGENT_INSTRUCTIONS = "You animate vector artwork. A scene is artwork (vector paths and groups, each with an id) plus shots.\n\nHow it plays\n- Shots play in order. A shot optionally moves the camera, plays its commands, then holds (default 600 ms).\n- Commands in a shot play one after another; give \"with\": \"previous\" to start one together with the command before, \"delay\" to wait, \"stagger\" to offset several targets.\n- Timing comes from the content: each command has a default length (enter 600 ms, move 700 ms, draw follows the path length). Only set \"duration\" to change the pace.\n- Anything that enters later is hidden until it enters. Things that never enter are visible from the start.\n- Every frame is a pure function of time: the same scene always plays the same frames.\n\nCommands\n- enter (fade, pop, grow, slide, draw) and exit (fade, shrink, slide, undraw) bring things in and out.\n- enter also reveals through a clip over the target's box: wipe (behind an edge travelling \"direction\", default right), iris (from the centre; \"shape\": circle or box) and split (from a line through the middle; \"orientation\": horizontal or vertical). exit wipe hides the same way. Reveals need a width and a height: use draw / undraw for a straight line.\n- draw draws strokes on to a fraction; move, rotate, scale and fade change the pose (about the centre); style blends solid colours and stroke width.\n- enter also has zoom (settles from larger) and rise (rises a short way, overshooting a touch); pop and zoom take a starting \"scale\".\n- morph turns a shape into another node's shape (keep the target hidden); match does the same for a whole group, part by part (Smart Animate: draw the end state as a second, hidden group whose parts share names with the first); follow moves along a path node (with \"rotate\", moves made meanwhile turn with the path).\n- Emphasis draws the eye and returns to rest: pulse (swell), shake (side to side, or \"axis\": \"vertical\"), teeter (rock), wave (bob, no settling), wiggle (seeded wander; the same seed wanders the same way) and color-pulse (tint and back).\n- Emphasis stacks on other motion: a shake during a slide shakes as it slides. Give move, rotate or scale \"blend\": \"add\" to stack them too (what they add stays); \"blend\": \"replace\" makes a change take over instead.\n- Any command but enter and exit can \"repeat\" (loop, mirror back and forth, or offset to carry on: rotate by 90, repeat 4 is a full turn); \"duration\" is one cycle.\n- Springs (\"spring-gentle\", \"spring-quick\", \"spring-bouncy\", \"spring-slow\" or { \"type\": \"spring\", \u2026 }) feel physical; leave \"duration\" out and the spring sets it.\n- To time shots to music or a voiceover: set a \"beat\" grid or \"narration\" word timings with set_animation_settings, read them with get_timing_grid, and give a shot \"at\": { \"beat\": n } or { \"word\": i }. The shot before holds until the cue; check_animation warns when a cue is missed.\n- \"steps\": 12 (on a command, or for the whole scene with set_animation_settings) holds poses \"on twos\" for a hand-drawn look. \"geometric\": true on scale or a camera zooms at an even rate.\n- Commands share their names and defaults with Flair's motion primitives (get_animation shows each one's \"flairPrimitive\"), and emphasis, reveals and follows export to Flair exactly.\n- effect tweens a numeric parameter of a live path effect already on the node (twist angle, wiggle time, zig zag size).\n\nWorking method\n1. get_animation to learn the element ids (set_animation_artwork_svg first if there is no artwork: give every element you will animate an id; or import_flair_effect to start from a Flair effect and edit it).\n2. Plan a few shots, each one idea. Add them with insert_shots (add_commands, update_command, move_command and delete_commands refine a shot), or edit_animation to make several edits as one step (dry_run first when unsure).\n3. To hit a length, fit_animation (keep the shots whose pace matters). check_animation and fix every error and warning; render_animation_frame (shot + \"end\") to look at the result; add onion_skin or motion_paths to see the motion in one picture, or get_motion_path for the numbers.\n- For something the viewer plays (a button, a toggle, a step-by-step explainer), set \"trigger\" with set_animation_settings: click plays the next shot on each click and then starts over (make the last shot put things back for a toggle), hover or press plays and rewinds, scroll scrubs.\n4. To make a reusable Flair effect, set_animation_controls (colour controls stand for every use of their default colour) and export_flair_effect.\n\nKeep motion purposeful: one thing moving at a time reads best, ease-out for arrivals, ease-in for exits, and hold long enough to see each result.";
|
|
1960
1965
|
|
|
1961
1966
|
/**
|
|
1962
1967
|
* Helpers for hand-editing UIs (React's and Svelte's command inspector, ease picker, cue picker,
|
|
@@ -31,8 +31,8 @@ interface MotionScene {
|
|
|
31
31
|
loop?: AnimationLoopMode;
|
|
32
32
|
/**
|
|
33
33
|
* Plays in answer to the viewer instead of on its own (exported to Flair's player):
|
|
34
|
-
* - `click`:
|
|
35
|
-
* a click plays the
|
|
34
|
+
* - `click`: nothing plays until the viewer clicks; each click plays the next shot, and after the
|
|
35
|
+
* last one a click plays the first again, so a last shot that puts things back makes a toggle.
|
|
36
36
|
* - `hover` / `press`: plays forward while the pointer is over (or down on) it, and back when it leaves.
|
|
37
37
|
* - `scroll`: scrubs through the scene as it scrolls through the viewport.
|
|
38
38
|
* The editor previews it played through; `loop` does not apply.
|
|
@@ -1238,7 +1238,7 @@ interface FlairMotionExport {
|
|
|
1238
1238
|
interface FlairExportOptions {
|
|
1239
1239
|
/**
|
|
1240
1240
|
* Play in answer to the viewer (default: the scene's `trigger`; null for none). With `click`
|
|
1241
|
-
*
|
|
1241
|
+
* shot n is Flair step n + 1: nothing plays until the first click, and each click plays the next shot.
|
|
1242
1242
|
*/
|
|
1243
1243
|
trigger?: MotionTrigger | null;
|
|
1244
1244
|
/** Sampling rate for changes Flair cannot express exactly (default: the scene's `fps`, else 30). */
|
|
@@ -1317,6 +1317,11 @@ interface FlairImportOptions {
|
|
|
1317
1317
|
name?: string;
|
|
1318
1318
|
/** Hold after the last shot, ms (default: the effect's `hold`, else 600). */
|
|
1319
1319
|
hold?: number;
|
|
1320
|
+
/**
|
|
1321
|
+
* The motion plays on click: Flair plays step 0 together with step 1 on the first click, so
|
|
1322
|
+
* both become the first shot (as `toFlairSvgMotion` writes them).
|
|
1323
|
+
*/
|
|
1324
|
+
clickSteps?: boolean;
|
|
1320
1325
|
}
|
|
1321
1326
|
/** A Flair `SvgMotion` as a scene (see the module notes for what carries over). */
|
|
1322
1327
|
declare function fromFlairSvgMotion(input: FlairSvgMotion, options?: FlairImportOptions): FlairImportResult;
|
|
@@ -1956,7 +1961,7 @@ declare function createAnimationEditorToolProvider(controller: AnimationEditorCo
|
|
|
1956
1961
|
* A short authoring guide for a model writing vector animations with the animation editor's
|
|
1957
1962
|
* tools. Static, so it caches well as part of a system prompt.
|
|
1958
1963
|
*/
|
|
1959
|
-
declare const ANIMATION_EDITOR_AGENT_INSTRUCTIONS = "You animate vector artwork. A scene is artwork (vector paths and groups, each with an id) plus shots.\n\nHow it plays\n- Shots play in order. A shot optionally moves the camera, plays its commands, then holds (default 600 ms).\n- Commands in a shot play one after another; give \"with\": \"previous\" to start one together with the command before, \"delay\" to wait, \"stagger\" to offset several targets.\n- Timing comes from the content: each command has a default length (enter 600 ms, move 700 ms, draw follows the path length). Only set \"duration\" to change the pace.\n- Anything that enters later is hidden until it enters. Things that never enter are visible from the start.\n- Every frame is a pure function of time: the same scene always plays the same frames.\n\nCommands\n- enter (fade, pop, grow, slide, draw) and exit (fade, shrink, slide, undraw) bring things in and out.\n- enter also reveals through a clip over the target's box: wipe (behind an edge travelling \"direction\", default right), iris (from the centre; \"shape\": circle or box) and split (from a line through the middle; \"orientation\": horizontal or vertical). exit wipe hides the same way. Reveals need a width and a height: use draw / undraw for a straight line.\n- draw draws strokes on to a fraction; move, rotate, scale and fade change the pose (about the centre); style blends solid colours and stroke width.\n- enter also has zoom (settles from larger) and rise (rises a short way, overshooting a touch); pop and zoom take a starting \"scale\".\n- morph turns a shape into another node's shape (keep the target hidden); match does the same for a whole group, part by part (Smart Animate: draw the end state as a second, hidden group whose parts share names with the first); follow moves along a path node (with \"rotate\", moves made meanwhile turn with the path).\n- Emphasis draws the eye and returns to rest: pulse (swell), shake (side to side, or \"axis\": \"vertical\"), teeter (rock), wave (bob, no settling), wiggle (seeded wander; the same seed wanders the same way) and color-pulse (tint and back).\n- Emphasis stacks on other motion: a shake during a slide shakes as it slides. Give move, rotate or scale \"blend\": \"add\" to stack them too (what they add stays); \"blend\": \"replace\" makes a change take over instead.\n- Any command but enter and exit can \"repeat\" (loop, mirror back and forth, or offset to carry on: rotate by 90, repeat 4 is a full turn); \"duration\" is one cycle.\n- Springs (\"spring-gentle\", \"spring-quick\", \"spring-bouncy\", \"spring-slow\" or { \"type\": \"spring\", \u2026 }) feel physical; leave \"duration\" out and the spring sets it.\n- To time shots to music or a voiceover: set a \"beat\" grid or \"narration\" word timings with set_animation_settings, read them with get_timing_grid, and give a shot \"at\": { \"beat\": n } or { \"word\": i }. The shot before holds until the cue; check_animation warns when a cue is missed.\n- \"steps\": 12 (on a command, or for the whole scene with set_animation_settings) holds poses \"on twos\" for a hand-drawn look. \"geometric\": true on scale or a camera zooms at an even rate.\n- Commands share their names and defaults with Flair's motion primitives (get_animation shows each one's \"flairPrimitive\"), and emphasis, reveals and follows export to Flair exactly.\n- effect tweens a numeric parameter of a live path effect already on the node (twist angle, wiggle time, zig zag size).\n\nWorking method\n1. get_animation to learn the element ids (set_animation_artwork_svg first if there is no artwork: give every element you will animate an id; or import_flair_effect to start from a Flair effect and edit it).\n2. Plan a few shots, each one idea. Add them with insert_shots (add_commands, update_command, move_command and delete_commands refine a shot), or edit_animation to make several edits as one step (dry_run first when unsure).\n3. To hit a length, fit_animation (keep the shots whose pace matters). check_animation and fix every error and warning; render_animation_frame (shot + \"end\") to look at the result; add onion_skin or motion_paths to see the motion in one picture, or get_motion_path for the numbers.\n- For something the viewer plays (a button, a toggle, a step-by-step explainer), set \"trigger\" with set_animation_settings: click plays the next shot on each click (make the last shot
|
|
1964
|
+
declare const ANIMATION_EDITOR_AGENT_INSTRUCTIONS = "You animate vector artwork. A scene is artwork (vector paths and groups, each with an id) plus shots.\n\nHow it plays\n- Shots play in order. A shot optionally moves the camera, plays its commands, then holds (default 600 ms).\n- Commands in a shot play one after another; give \"with\": \"previous\" to start one together with the command before, \"delay\" to wait, \"stagger\" to offset several targets.\n- Timing comes from the content: each command has a default length (enter 600 ms, move 700 ms, draw follows the path length). Only set \"duration\" to change the pace.\n- Anything that enters later is hidden until it enters. Things that never enter are visible from the start.\n- Every frame is a pure function of time: the same scene always plays the same frames.\n\nCommands\n- enter (fade, pop, grow, slide, draw) and exit (fade, shrink, slide, undraw) bring things in and out.\n- enter also reveals through a clip over the target's box: wipe (behind an edge travelling \"direction\", default right), iris (from the centre; \"shape\": circle or box) and split (from a line through the middle; \"orientation\": horizontal or vertical). exit wipe hides the same way. Reveals need a width and a height: use draw / undraw for a straight line.\n- draw draws strokes on to a fraction; move, rotate, scale and fade change the pose (about the centre); style blends solid colours and stroke width.\n- enter also has zoom (settles from larger) and rise (rises a short way, overshooting a touch); pop and zoom take a starting \"scale\".\n- morph turns a shape into another node's shape (keep the target hidden); match does the same for a whole group, part by part (Smart Animate: draw the end state as a second, hidden group whose parts share names with the first); follow moves along a path node (with \"rotate\", moves made meanwhile turn with the path).\n- Emphasis draws the eye and returns to rest: pulse (swell), shake (side to side, or \"axis\": \"vertical\"), teeter (rock), wave (bob, no settling), wiggle (seeded wander; the same seed wanders the same way) and color-pulse (tint and back).\n- Emphasis stacks on other motion: a shake during a slide shakes as it slides. Give move, rotate or scale \"blend\": \"add\" to stack them too (what they add stays); \"blend\": \"replace\" makes a change take over instead.\n- Any command but enter and exit can \"repeat\" (loop, mirror back and forth, or offset to carry on: rotate by 90, repeat 4 is a full turn); \"duration\" is one cycle.\n- Springs (\"spring-gentle\", \"spring-quick\", \"spring-bouncy\", \"spring-slow\" or { \"type\": \"spring\", \u2026 }) feel physical; leave \"duration\" out and the spring sets it.\n- To time shots to music or a voiceover: set a \"beat\" grid or \"narration\" word timings with set_animation_settings, read them with get_timing_grid, and give a shot \"at\": { \"beat\": n } or { \"word\": i }. The shot before holds until the cue; check_animation warns when a cue is missed.\n- \"steps\": 12 (on a command, or for the whole scene with set_animation_settings) holds poses \"on twos\" for a hand-drawn look. \"geometric\": true on scale or a camera zooms at an even rate.\n- Commands share their names and defaults with Flair's motion primitives (get_animation shows each one's \"flairPrimitive\"), and emphasis, reveals and follows export to Flair exactly.\n- effect tweens a numeric parameter of a live path effect already on the node (twist angle, wiggle time, zig zag size).\n\nWorking method\n1. get_animation to learn the element ids (set_animation_artwork_svg first if there is no artwork: give every element you will animate an id; or import_flair_effect to start from a Flair effect and edit it).\n2. Plan a few shots, each one idea. Add them with insert_shots (add_commands, update_command, move_command and delete_commands refine a shot), or edit_animation to make several edits as one step (dry_run first when unsure).\n3. To hit a length, fit_animation (keep the shots whose pace matters). check_animation and fix every error and warning; render_animation_frame (shot + \"end\") to look at the result; add onion_skin or motion_paths to see the motion in one picture, or get_motion_path for the numbers.\n- For something the viewer plays (a button, a toggle, a step-by-step explainer), set \"trigger\" with set_animation_settings: click plays the next shot on each click and then starts over (make the last shot put things back for a toggle), hover or press plays and rewinds, scroll scrubs.\n4. To make a reusable Flair effect, set_animation_controls (colour controls stand for every use of their default colour) and export_flair_effect.\n\nKeep motion purposeful: one thing moving at a time reads best, ease-out for arrivals, ease-in for exits, and hold long enough to see each result.";
|
|
1960
1965
|
|
|
1961
1966
|
/**
|
|
1962
1967
|
* Helpers for hand-editing UIs (React's and Svelte's command inspector, ease picker, cue picker,
|
|
@@ -1501,7 +1501,7 @@ function checkMotionScene(scene) {
|
|
|
1501
1501
|
if (scene.trigger) {
|
|
1502
1502
|
if ((scene.loop ?? "none") !== "none") issues.push(motionIssue("trigger-loop", `The scene plays on ${scene.trigger}, so its "${scene.loop}" loop does not apply; set loop to "none" or remove the trigger.`, {}));
|
|
1503
1503
|
if (scene.trigger === "click") {
|
|
1504
|
-
if (scene.shots.length === 1) issues.push(motionIssue("click-one-shot", "The scene plays on click but has one shot, so every click replays it from the start; split it into shots (
|
|
1504
|
+
if (scene.shots.length === 1) issues.push(motionIssue("click-one-shot", "The scene plays on click but has one shot, so every click replays it from the start; split it into shots (each click plays the next one).", { shot: scene.shots[0].id }));
|
|
1505
1505
|
scene.shots.forEach((shot, i) => {
|
|
1506
1506
|
if (i > 0 && shot.at) issues.push(motionIssue("click-cue", `Shot "${shot.id}" is cued, but on click a shot starts when it is clicked to; remove its "at" or the trigger.`, { shot: shot.id }));
|
|
1507
1507
|
});
|
|
@@ -2065,7 +2065,7 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
2065
2065
|
animate.sort((x, y) => (x.delay ?? 0) - (y.delay ?? 0));
|
|
2066
2066
|
const lastChange = animate.reduce((m, a) => Math.max(m, (a.delay ?? 0) + (a.ms ?? 0)), 0);
|
|
2067
2067
|
const trigger = options.trigger === null ? void 0 : options.trigger ?? scene.trigger;
|
|
2068
|
-
if (trigger === "click" && timeline.shots.length
|
|
2068
|
+
if (trigger === "click" && timeline.shots.length) {
|
|
2069
2069
|
for (const a of animate) {
|
|
2070
2070
|
const at = a.delay ?? 0;
|
|
2071
2071
|
let step = 0;
|
|
@@ -2075,7 +2075,7 @@ function toFlairSvgMotion(scene, options = {}) {
|
|
|
2075
2075
|
const delay = round2(at - timeline.shots[step].start);
|
|
2076
2076
|
delete a.delay;
|
|
2077
2077
|
if (delay > 0) a.delay = delay;
|
|
2078
|
-
|
|
2078
|
+
a.step = step + 1;
|
|
2079
2079
|
}
|
|
2080
2080
|
animate.sort((x, y) => (x.step ?? 0) - (y.step ?? 0) || (x.delay ?? 0) - (y.delay ?? 0));
|
|
2081
2081
|
}
|
|
@@ -2260,7 +2260,8 @@ function fromFlairSvgMotion(input, options = {}) {
|
|
|
2260
2260
|
const nodes = indexMotionNodes(artwork.nodes);
|
|
2261
2261
|
const byStep = /* @__PURE__ */ new Map();
|
|
2262
2262
|
for (const anim of motion.animate ?? []) {
|
|
2263
|
-
const
|
|
2263
|
+
const raw = Math.max(0, Math.floor(anim.step ?? 0));
|
|
2264
|
+
const step = options.clickSteps ? Math.max(1, raw) : raw;
|
|
2264
2265
|
if (!byStep.has(step)) byStep.set(step, []);
|
|
2265
2266
|
byStep.get(step).push(anim);
|
|
2266
2267
|
}
|
|
@@ -2311,7 +2312,7 @@ function presetColor(value) {
|
|
|
2311
2312
|
}
|
|
2312
2313
|
function fromFlairVectorEffect(effect, options = {}) {
|
|
2313
2314
|
if (!effect || effect.kind !== "vector" || !effect.motion) throw new Error('Give a Flair vector effect: { kind: "vector", id, name, motion: { svg, animate } }.');
|
|
2314
|
-
const result = fromFlairSvgMotion(effect.motion, { name: options.name ?? effect.id ?? effect.name, hold: options.hold ?? effect.hold });
|
|
2315
|
+
const result = fromFlairSvgMotion(effect.motion, { name: options.name ?? effect.id ?? effect.name, hold: options.hold ?? effect.hold, ...effect.trigger === "click" ? { clickSteps: true } : {} });
|
|
2315
2316
|
const names = new Set((result.scene.controls ?? []).map((c) => c.name));
|
|
2316
2317
|
const presets = (effect.presets ?? []).map((p) => ({ name: p.name, values: Object.fromEntries(Object.entries(p.values).flatMap(([k, v]) => names.has(k) && presetColor(v) ? [[k, presetColor(v)]] : [])) })).filter((p) => Object.keys(p.values).length);
|
|
2317
2318
|
const scene = { ...result.scene, ...effect.description ? { description: effect.description } : {}, ...presets.length ? { presets } : {}, ...effect.trigger ? { trigger: effect.trigger } : {} };
|
|
@@ -3025,7 +3026,7 @@ var SETTINGS = {
|
|
|
3025
3026
|
loop: { type: "string", enum: ["none", "loop", "ping-pong"], description: "Playback past the end (default none)." },
|
|
3026
3027
|
trigger: {
|
|
3027
3028
|
anyOf: [{ type: "string", enum: ["click", "hover", "press", "scroll"] }, { type: "null" }],
|
|
3028
|
-
description: "Play in answer to the viewer when exported to Flair: click (
|
|
3029
|
+
description: "Play in answer to the viewer when exported to Flair: click (nothing plays until a click; each click plays the next shot, then the first again), hover or press (plays while the pointer is over or down, rewinds when it leaves), scroll (scrubs as it scrolls past). null plays on its own (default). The editor previews it played through."
|
|
3029
3030
|
},
|
|
3030
3031
|
fps: { type: "number", minimum: 1, maximum: 120, description: "Sampling rate for exports (default 30)." },
|
|
3031
3032
|
steps: { anyOf: [{ type: "number", exclusiveMinimum: 0, maximum: 120 }, { type: "null" }], description: 'Stepped time for every command without its own: changes hold on a grid of this many frames per second (12 = "on twos" at 24 fps) for a hand-drawn look; null makes it smooth again (default).' },
|
|
@@ -3621,7 +3622,7 @@ Working method
|
|
|
3621
3622
|
1. get_animation to learn the element ids (set_animation_artwork_svg first if there is no artwork: give every element you will animate an id; or import_flair_effect to start from a Flair effect and edit it).
|
|
3622
3623
|
2. Plan a few shots, each one idea. Add them with insert_shots (add_commands, update_command, move_command and delete_commands refine a shot), or edit_animation to make several edits as one step (dry_run first when unsure).
|
|
3623
3624
|
3. To hit a length, fit_animation (keep the shots whose pace matters). check_animation and fix every error and warning; render_animation_frame (shot + "end") to look at the result; add onion_skin or motion_paths to see the motion in one picture, or get_motion_path for the numbers.
|
|
3624
|
-
- For something the viewer plays (a button, a toggle, a step-by-step explainer), set "trigger" with set_animation_settings: click plays the next shot on each click (make the last shot
|
|
3625
|
+
- For something the viewer plays (a button, a toggle, a step-by-step explainer), set "trigger" with set_animation_settings: click plays the next shot on each click and then starts over (make the last shot put things back for a toggle), hover or press plays and rewinds, scroll scrubs.
|
|
3625
3626
|
4. To make a reusable Flair effect, set_animation_controls (colour controls stand for every use of their default colour) and export_flair_effect.
|
|
3626
3627
|
|
|
3627
3628
|
Keep motion purposeful: one thing moving at a time reads best, ease-out for arrivals, ease-in for exits, and hold long enough to see each result.`;
|