# Animation (lv_anim) (/main-modules/animation)





Animations allow you to define the way something should move or change over time, and
let LVGL do the heavy lifting of making it happen.  What makes it so powerful is that
the thing being changed can be virtually anything in your system.  It is very
convenient to apply this to LVGL Widgets in your user interface (UI), to change their
appearance, size or location over time.  But because it is --- at its core --- a
generic change-over-time manager, complete with a variety of optional event
callbacks, its application can be wider than just to UI components.

For each Animation you create, it accomplishes the above by providing a generic
method of varying a signed integer from a start value to an end value over a
specified time period.  It allows you to specify what object it applies to (the
"variable"), which is available in the callback functions that are called as the
Animation is playing through.

This variation over time can be linear (default), it can be on a path (curve) that
you specify, and there is even a variety of commonly-used non-linear effects that can
be specified.

The main callback called during an Animation (when it is playing) is called an
*animator* function, which has the following prototype:

```c title=" " lineNumbers=1
void func(void *var , int32_t value);
```

This prototype makes it easy to use most of the LVGL *set* functions directly or via a trivial wrapper. It includes:

* most of the widget properties
* functions that set [local style properties](/common-widget-features/styles/local_styles) directly on objects (needs a wrapper to set the *selector*)
* set properties on <ApiLink name="lv_style_t" /> objects (e.g. [shared styles](/common-widget-features/styles/style_sheets))  (`lv_obj_report_style_change` needs to be called to notify the widgets having the style)
* `lv_style_set_<property_name>(&style, <value>)`
* `lv_obj_set_<property_name>(widget, <value>)`

Using `lv_style_set_<property_name>(&shared_style, <value>)`, an animation on a
single <ApiLink name="lv_style_t" /> object shared
among several objects can simultaneously modify the appearance of all objects that
use it.  See [Styles](/common-widget-features/styles) for more details.

Examples of `lv_obj_set_<property_name>(widget, <value>)` are:
<ApiLink name="lv_obj_set_x" display="lv_obj_set_x(widget, value)" /> or
<ApiLink name="lv_obj_set_width" display="lv_obj_set_width(widget, value)" />.

This makes it very convenient to apply to the appearance (and other attributes) of UI
components.  You can also provide your own "set" functions, so the application of
Animations is really limited only by your imagination.

The number of Animations that can be playing at the same time for a given object with
a given *animator* callback is one (1).  However, the number of Animations that can
be playing at the same time is limited only by available RAM and CPU time for:

* a given object with different *animator* callbacks; and
* different objects.

Thus, you can have a Button's width being changed by one Animation while having its
height being changed by another Animation.

Creating an Animation [#creating-an-animation]

To create an Animation, start by creating an Animation *template* in an
<ApiLink name="lv_anim_t" /> variable.  It has to be initialized and configured with
`lv_anim_set_...()` functions.

```c title=" " lineNumbers=1
/* INITIALIZE AN ANIMATION
 *-----------------------*/

static lv_anim_t   anim_template;
static lv_anim_t * running_anim;

lv_anim_init(&anim_template);

/* MANDATORY SETTINGS
 *------------------*/

/* Set the "animator" function */
lv_anim_set_exec_cb(&anim_template, (lv_anim_exec_xcb_t) lv_obj_set_x);

/* Set target of the Animation */
lv_anim_set_var(&anim_template, widget);

/* Length of the Animation [ms] */
lv_anim_set_duration(&anim_template, duration_in_ms);

/* Set start and end values. E.g. 0, 150 */
lv_anim_set_values(&anim_template, start, end);

/* OPTIONAL SETTINGS
 *------------------*/

/* Time to wait before starting the Animation [ms] */
lv_anim_set_delay(&anim_template, delay);

/* Set path (curve). Default is linear */
lv_anim_set_path_cb(&anim_template, lv_anim_path_ease_in);

/* Set anim_template callback to indicate when the Animation is completed. */
lv_anim_set_completed_cb(&anim_template, completed_cb);

/* Set anim_template callback to indicate when the Animation is deleted (idle). */
lv_anim_set_deleted_cb(&anim_template, deleted_cb);

/* Set anim_template callback to indicate when the Animation is started (after delay). */
lv_anim_set_start_cb(&anim_template, start_cb);

/* When ready, play the Animation backward with this duration. Default is 0 (disabled) [ms] */
lv_anim_set_reverse_duration(&anim_template, time);

/* Delay before reverse play. Default is 0 (disabled) [ms] */
lv_anim_set_reverse_delay(&anim_template, delay);

/* Number of repetitions. Default is 1. LV_ANIM_REPEAT_INFINITE for infinite repetition */
lv_anim_set_repeat_count(&anim_template, cnt);

/* Delay before repeat. Default is 0 (disabled) [ms] */
lv_anim_set_repeat_delay(&anim_template, delay);

/* Apply the start value immediately (default true); false: apply start value after
 * delay when the Animation actually starts. */
lv_anim_set_early_apply(&anim_template, true/false);

/* START THE ANIMATION
 *------------------*/
running_anim = lv_anim_start(&anim_template);   /* Start the Animation */
```

Animation Path [#animation-path]

You can control the Path (rate curve) of an Animation.  The simplest case is linear,
meaning the current value between *start* and *end* is changed at the same rate (i.e.
with fixed steps) over the duration of the Animation.  A *Path* is a function which
calculates the next value to set based on the current state of the Animation.
There are a number of built-in *Paths* that can be used:

* <ApiLink name="lv_anim_path_linear" />: linear animation (default)
* <ApiLink name="lv_anim_path_step" />: change in one step at the end
* <ApiLink name="lv_anim_path_ease_in" />: slow at the beginning
* <ApiLink name="lv_anim_path_ease_out" />: slow at the end
* <ApiLink name="lv_anim_path_ease_in_out" />: slow at the beginning and end
* <ApiLink name="lv_anim_path_overshoot" />: overshoot the end value
* <ApiLink name="lv_anim_path_bounce" />: bounce back a little from the end value (like
  hitting a wall)

Alternately, you can provide your own Path function.

<ApiLink name="lv_anim_init" display="lv_anim_init(&my_anim)" /> sets the Path to <ApiLink name="lv_anim_path_linear" />
by default.  If you want to use a different Path (including a custom Path function
you provide), set it using <ApiLink name="lv_anim_set_path_cb" display="lv_anim_set_path_cb(&anim_template, path_cb)" />.

If you provide your own custom Path function, its prototype is:

```c title=" " lineNumbers=1
int32_t   calculate_value(lv_anim_t * anim);
```

Speed vs Time [#speed-vs-time]

Normally, you set the Animation duration directly using
<ApiLink name="lv_anim_set_duration" display="lv_anim_set_duration(&anim_template, duration_in_ms)" />.  But in some cases
the *rate* is known but the duration is not known.  Given an Animation's `start`
and `end` values, *rate* here means the number of units of change per second, i.e.
how quickly (units per second) the Animation's value needs to change between the
`start` and `end` value.  For such cases there is a utility function
<ApiLink name="lv_anim_speed_to_time" /> you can use to compute the Animation's duration, so
you can set it like this:

```c title=" " lineNumbers=1
uint32_t  change_per_sec = 20;
uint32_t  duration_in_ms = lv_anim_speed_to_time(change_per_sec, 0, 100);
/* `duration_in_ms` will be 5000 */
lv_anim_set_duration(&anim_template, duration_in_ms);
```

Animating in Both Directions [#animating-in-both-directions]

Sometimes an Animation needs to play forward, and then play backwards, effectively
reversing course, animating from the `end` value back to the `start` value again.
To do this, pass a non-zero value to this function to set the duration for the
reverse portion of the Animation:
<ApiLink name="lv_anim_set_reverse_duration" display="lv_anim_set_reverse_duration(&anim_template, duration_in_ms)" />.

Optionally, you can also introduce a delay between the forward and backward
directions using <ApiLink name="lv_anim_set_reverse_delay" display="lv_anim_set_reverse_delay(&anim_template, delay_in_ms)" />

Starting an Animation [#starting-an-animation]

After you have set up your <ApiLink name="lv_anim_t" /> object, it is important to realize
that what you have set up is a "template" for a live, running Animation that has
not been created yet.  When you call <ApiLink name="lv_anim_start" display="lv_anim_start(&anim_template)" />
passing the *template* you have set up, it uses your template to dynamically allocate
an internal object that is a *live, running* Animation.  This function returns a
pointer to that object.

```c title=" " lineNumbers=1
static lv_anim_t   anim_template;
static lv_anim_t * running_anim;

/* Set up template... */
lv_anim_init(&anim_template);
/* ...and other set-up functions above. */

/* Later... */
running_anim = lv_anim_start(&anim_template);
```

<Callout type="info">
  template, so if you do not need it later, its contents do not need to be
  preserved after this call.
</Callout>

Once a *live running* Animation has been started, it runs until it has completed,
or until it is deleted (see below), whichever comes first.  An Animation has
completed when:

* its "value" has reached the designated `end` value;
* if the Animation has a non-zero *reverse* duration value, then its value
  has run from the `end` value back to the `start` value again;
* if a non-zero repeat count has been set, it has repeated the Animation
  that number of times.

Once the *live, running* Animation reaches completion, it is automatically deleted
from the list of running Animations.  This does not impact your Animation template.

<Callout type="info">
  If <ApiLink name="lv_anim_set_repeat_count" display="lv_anim_set_repeat_count(&anim_template, cnt)" /> has been called
  passing <ApiLink name="LV_ANIM_REPEAT_INFINITE" />, the animation never reaches a state
  of being "completed".  In this case, it must be deleted to terminate the
  Animation.
</Callout>

Deleting Animations [#deleting-animations]

You should delete an Animation using <ApiLink name="lv_anim_delete" display="lv_anim_delete(var, func)" /> if one of
these two conditions exists:

* the object (variable) being animated is deleted (and it is not a Widget) or
* a running animation needs to be stopped before it is completed.

<Callout type="info">
  If the object (variable) being deleted is a type of Widget, the housekeeping code
  involved in deleting it also deletes any running animations that are connected
  with it.  So <ApiLink name="lv_anim_delete" display="lv_anim_delete(var, func)" /> only needs to be called if the
  object being deleted is *not* one of the Widgets.
</Callout>

If you kept a copy of the pointer returned by <ApiLink name="lv_anim_start" /> as
`running_anim`, you can delete the running animation like this:

```c title=" " lineNumbers=1
lv_anim_delete(running_anim->var, running_anim->exec_cb);
```

In the event that the Animation completes *after* you have determined it needs to be
deleted, and before the call to <ApiLink name="lv_anim_delete" /> is made, it does no harm
to call it a second time --- no damage will occur.

This function returns a Boolean value indicating whether any *live, running*
Animations were deleted.

Pausing Animations [#pausing-animations]

If you kept a copy of the pointer returned by <ApiLink name="lv_anim_start" />,
you can pause the running animation using <ApiLink name="lv_anim_pause" display="lv_anim_pause(animation)" /> and then resume it
using <ApiLink name="lv_anim_resume" display="lv_anim_resume(animation)" />.

<ApiLink name="lv_anim_pause_for" display="lv_anim_pause_for(animation, milliseconds)" />

is also available if you wish for the animation to resume automatically after.

Timelines [#timelines]

You can create a series of related animations that are linked together using an
Animation Timeline.  A Timeline is a collection of multiple Animations which makes it
easy to create complex composite Animations.

<img alt="Anim Timeline" src="__img0" />

To create and use an Animation Timeline:

* Create an Animation template but do not call <ApiLink name="lv_anim_start" /> on it.
* Create an Animation Timeline object by calling <ApiLink name="lv_anim_timeline_create" />.
* Add Animation templates to the Timeline by calling
  <ApiLink name="lv_anim_timeline_add" display="lv_anim_timeline_add(timeline, start_time, &anim_template)" />.
  `start_time` is the start time of the Animation on the Timeline.  Note that
  `start_time` will override any value given to
  <ApiLink name="lv_anim_set_delay" display="lv_anim_set_delay(&anim_template, delay)" />.
* Call <ApiLink name="lv_anim_timeline_start" display="lv_anim_timeline_start(timeline)" /> to start the Animation Timeline.

<Callout type="info">
  own copy of the contents of the Animation template, so if you do not need it
  later, its contents do not need to be preserved after this call.
</Callout>

It supports forward and reverse play of the entire Animation group, using
<ApiLink name="lv_anim_timeline_set_reverse" display="lv_anim_timeline_set_reverse(timeline, reverse)" />. Note that if you want to
play in reverse from the end of the Timeline, you need to call

<ApiLink name="lv_anim_timeline_set_progress" display="lv_anim_timeline_set_progress(timeline, LV_ANIM_TIMELINE_PROGRESS_MAX)" />

after adding all Animations and before telling it to start playing.

Call <ApiLink name="lv_anim_timeline_pause" display="lv_anim_timeline_pause(timeline)" /> to pause the Animation Timeline.
Note:  this does not preserve its state.  The only way to start it again is to call
<ApiLink name="lv_anim_timeline_start" display="lv_anim_timeline_start(timeline)" />, which starts the Timeline from the
beginning or at the point set by
<ApiLink name="lv_anim_timeline_set_progress" display="lv_anim_timeline_set_progress(timeline, progress)" />.

Call <ApiLink name="lv_anim_timeline_set_progress" display="lv_anim_timeline_set_progress(timeline, progress)" /> function to set the
state of the Animation Timeline according to the `progress` value.  `progress` is
a value between `0` and `65535` (<ApiLink name="LV_ANIM_TIMELINE_PROGRESS_MAX" />) to indicate the
proportion of the Timeline that has "played".  Example:  a `progress` value of
<ApiLink name="LV_ANIM_TIMELINE_PROGRESS_MAX" display="LV_ANIM_TIMELINE_PROGRESS_MAX / 2" /> would set the Timeline play to its
half-way point.

Call <ApiLink name="lv_anim_timeline_get_playtime" display="lv_anim_timeline_get_playtime(timeline)" /> function to get the total
duration (in milliseconds) of the entire Animation Timeline.

Call <ApiLink name="lv_anim_timeline_get_reverse" display="lv_anim_timeline_get_reverse(timeline)" /> function to get whether the
Animation Timeline is also played in reverse after its forward play completes.

Call <ApiLink name="lv_anim_timeline_delete" display="lv_anim_timeline_delete(timeline)" /> function to delete the Animation Timeline.

<Callout type="warn">
  If you need to delete a Widget during Animation, be sure to delete the Animation
  Timeline before deleting the Widget. Otherwise, the program may crash or behave
  abnormally.
</Callout>

<Callout type="warn">
  To prevent undefined behavior, the Animations subsystem does not allow more than
  one Animation to execute concurrently when they modify the same target object
  with the same *animator* callback.

  If you have set up an Animation Timeline from 2 or more Animation Templates with
  these characteristics, be aware that when the Animation is started for any of
  them, the Animation subsystem looks for such cases and considers it a conflict
  when:

  * more than one are running concurrently, or
  * more than one have their "early apply" behavior turned on (which it is by default).

  When this is detected, all such Animations are deleted except for the one most
  recently added.

  To avoid this, if you want to use more than one Animation Template that updates
  the same object using the same *animator* callback:

  * ensure that all but the first one to execute in the Timeline have their
    "early apply" default behavior turned off before starting the Timeline, and
  * ensure that they do not execute concurrently.

  Example:

  ```c title=" " lineNumbers=1
  /* These 4 Animation Templates execute in an Animation Timeline in the numbered
   * sequence, and they modify the same object using the same callback. */
  lv_anim_t anim_template_1;
  lv_anim_t anim_template_2;
  lv_anim_t anim_template_3;
  lv_anim_t anim_template_4;

  /* Initialization code for all 4 of them here. */

  /* Ensure these steps are made before the Timeline is started. */
  lv_anim_set_early_apply(&anim_template_2, false);
  lv_anim_set_early_apply(&anim_template_3, false);
  lv_anim_set_early_apply(&anim_template_4, false);

  /* Start Timeline */
  lv_anim_timeline_start(timeline);
  ```
</Callout>

Examples [#examples]

Start animation on an event [#start-animation-on-an-event]

<LvglExample name="lv_example_anim_1" path="anim/lv_example_anim_1" />

Playback animation [#playback-animation]

<LvglExample name="lv_example_anim_2" path="anim/lv_example_anim_2" />

Cubic Bezier animation [#cubic-bezier-animation]

<LvglExample name="lv_example_anim_3" path="anim/lv_example_anim_3" />

Pause animation [#pause-animation]

<LvglExample name="lv_example_anim_4" path="anim/lv_example_anim_4" />

Animation timeline [#animation-timeline]

<LvglExample name="lv_example_anim_timeline_1" path="anim/lv_example_anim_timeline_1" />

API [#api]
