-
Notifications
You must be signed in to change notification settings - Fork 656
docs: variants, bind_style if, transitions, easing #414
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
cdbb6f1
7c3acef
af4f8b7
3a2dbd7
f0d9cc2
c95bb2d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,15 +7,17 @@ Create smooth, professional animations for your UI components using LVGL's timel | |
|
|
||
| ## Overview | ||
|
|
||
| XML animations are built on timeline animations that organize multiple animation steps into coordinated sequences. | ||
| XML animations are used to animate one or more widgets and their properties. They are built from timeline animations that organize multiple animation steps into coordinated sequences. | ||
|
|
||
| Timelines are composed of simple animations. For example: *"change the `bg_opa` of `my_button_2` from 0 to 255 in 500 ms."* | ||
|
|
||
| Each Component can define its own timeline animations, which can then be played by the Component itself or by any parent Components. | ||
|
|
||
| Style [`<transition>`](./styles#transitions)s can animate widgets too. The difference is what starts them: a timeline is played on demand, while a transition runs when the widget's state changes, for example from default to pressed. | ||
|
|
||
| ## Defining Timelines | ||
|
|
||
| Timelines can be defined inside [`<screen>`](./screens)s and [`<component>`](./components)s. | ||
| Timelines can be defined inside [`<screen>`](./screens)s and [`<component>`](./components)s. | ||
|
|
||
| Example: | ||
|
|
||
|
|
@@ -31,9 +33,9 @@ Example: | |
|
|
||
| <!-- Shake horizontally --> | ||
| <timeline name="shake" repeat_count="infinite" repeat_delay="200"> | ||
| <animation prop="translate_x" target="self" start="0" end="-30" duration="150"/> | ||
| <animation prop="translate_x" target="self" start="-30" end="30" duration="300" delay="150"/> | ||
| <animation prop="translate_x" target="self" start="30" end="0" duration="150" delay="450"/> | ||
| <animation prop="translate_x" target="self" start="0" end="-30" duration="150" easing="ease_in_out"/> | ||
| <animation prop="translate_x" target="self" start="-30" end="30" duration="300" delay="150" easing="ease_in_out"/> | ||
| <animation prop="translate_x" target="self" start="30" end="0" duration="150" delay="450" easing="ease_in_out"/> | ||
| </timeline> | ||
| </animations> | ||
|
|
||
|
|
@@ -54,7 +56,7 @@ Inside `<animations>`, you can define `<timeline>`s with unique names that you c | |
| - `repeat_count` - How many times the whole timeline repeats. Use a number, or `infinite` to loop forever. Default is `1`. | ||
| - `repeat_delay` - Delay in milliseconds between repetitions. Default is `0`. | ||
|
|
||
| ### Simple Animations | ||
| ### Simple Animations | ||
|
|
||
| Within each `timeline`, add individual `<animation>` elements to describe each step. The following properties are supported: | ||
|
|
||
|
|
@@ -63,10 +65,63 @@ Within each `timeline`, add individual `<animation>` elements to describe each s | |
| - `target` - Name of the UI element to animate. `self` refers to the root element of the Component (the `view`). | ||
| - `start` - Start value (integer only). | ||
| - `end` - End value (integer only). | ||
| - `duration` - Duration of the animation in milliseconds. | ||
| - `duration` - Duration of the animation in milliseconds. Default is `1000`. | ||
| - `delay` - Delay before starting in milliseconds. Default is 0. | ||
| - `early_apply` - If `true`, the start value is applied immediately, even during the delay. Default is `false`. | ||
| - `easing` - The animation path, e.g. `ease_out`. See below. Default is `linear`. | ||
|
|
||
| `start`, `end`, `duration` and `delay` accept constants and [expressions](./evaluate#outside-the-view) of them: | ||
|
|
||
| ```xml | ||
| <consts> | ||
| <int name="slide_ms" value="500"/> | ||
| <int name="slide_dist" value="30"/> | ||
| </consts> | ||
|
|
||
| <animation prop="translate_x" target="self" start="{-slide_dist}" end="0" | ||
| duration="{slide_ms}" delay="{slide_ms / 2}"/> | ||
| ``` | ||
|
|
||
| ### Easing | ||
|
|
||
| The `easing` property tells how the value should progress from `start` to `end` during the `duration`. These built-in paths can be used: | ||
|
|
||
| - `linear` - Constant speed. This is the default. | ||
| - `ease_in` - Slow start. | ||
| - `ease_out` - Slow end. | ||
| - `ease_in_out` - Slow start and end. | ||
| - `overshoot` - Goes above the end value and settles back. | ||
| - `bounce` - Bounces back a few times at the end. | ||
| - `step` - Stays at the start value and jumps to the end value at the very end. | ||
|
|
||
| ```xml | ||
| <animation prop="translate_y" target="self" start="-30" end="0" duration="500" easing="ease_out"/> | ||
| ``` | ||
|
|
||
| For full control, `bezier(x1 y1 x2 y2)` describes a cubic bezier curve with its two control points, just like `cubic-bezier()` in CSS: | ||
|
|
||
| ```xml | ||
| <animation prop="translate_y" target="self" start="-30" end="0" duration="500" | ||
| easing="bezier(0.34 1.56 0.64 1)"/> | ||
| ``` | ||
|
|
||
| `x1` and `x2` need to be in the `0..1` range, while `y1` and `y2` can be outside it to overshoot. At most four decimals are used from each value. Ready to use curves can be picked from e.g. [easings.net](https://easings.net). | ||
|
|
||
| Finally, an animation path implemented in C can be referenced by its function name: | ||
|
|
||
| ```xml | ||
| <animation prop="translate_y" target="self" start="-30" end="0" duration="500" easing="my_easing"/> | ||
| ``` | ||
|
|
||
| ```c | ||
| int32_t my_easing(const lv_anim_t * a) | ||
| { | ||
| /*Return the value to apply now, interpolating between start_value and end_value*/ | ||
| return lv_map(a->act_time, 0, a->duration, a->start_value, a->end_value); | ||
| } | ||
| ``` | ||
|
|
||
| The exported code calls this function directly, so it can't be `static` and it has to be visible where the generated file is compiled. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: This change rewrites the C-easing documentation to claim that an easing path is referenced directly by its function name (non-static, no registration, plain C function the generated file calls). That directly contradicts the same repo's AGENTS.md (docs/../AGENTS.md, Animations section), which still states: "easing ... or a callback registered with Prompt for AI agents-Register the callback before the XML that uses it, as the name is resolved while the XML is being parsed. In the exported code the name is emitted as a plain C function reference, so the function has to be visible to the generated file. Include External Timelines</file context> |
||
|
|
||
| ### Include External Timelines | ||
|
|
||
|
|
@@ -96,4 +151,4 @@ The created timeline instances and their names are saved in the Component's inst | |
|
|
||
| When a `play_timeline_event` is added to a UI element, the target and timeline names are saved as strings. Pointers cannot be used because the event can reference UI elements that will be created only later in the `view`. | ||
|
|
||
| Finally, when the play timeline event is triggered, the selected timeline is retrieved by its name from the target and started according to the other parameters (reverse, delay, and so on). | ||
| Finally, when the play timeline event is triggered, the selected timeline is retrieved by its name from the target and started according to the other parameters (reverse, delay, and so on). | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3: A non-subject
$propinside@{ }is described as "an error", which contradicts both this paragraph's own soft-failure theme and the authoritative docs/syntax/data-binding.mdx, where it is "skipped with a warning, but the widget is still created normally". Consider rewording to "skipped with a warning" so users don't expect a hard failure that doesn't occur.Prompt for AI agents