mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-14 06:42:58 +08:00
289 lines
9.3 KiB
ReStructuredText
289 lines
9.3 KiB
ReStructuredText
.. _rlottie:
|
|
|
|
=============
|
|
Lottie player
|
|
=============
|
|
|
|
Allows playing Lottie animations in LVGL. Taken from `lv_rlottie <https://github.com/ValentiWorkLearning/lv_rlottie>`__.
|
|
|
|
LVGL provides the interface to `Samsung/rlottie <https://github.com/Samsung/rlottie>`__ library's C
|
|
API. That is the actual Lottie player is not part of LVGL, it needs to
|
|
be built separately.
|
|
|
|
Build Rlottie
|
|
-------------
|
|
|
|
To build Samsung's Rlottie C++14 compatible compiler and optionally
|
|
CMake 3.14 or higher is required.
|
|
|
|
To build on desktop you can follow the instructions from Rlottie's
|
|
`README <https://github.com/Samsung/rlottie/blob/master/README.md>`__.
|
|
|
|
In the most basic case it looks like this:
|
|
|
|
.. code:: shell
|
|
|
|
mkdir rlottie_workdir
|
|
cd rlottie_workdir
|
|
git clone https://github.com/Samsung/rlottie.git
|
|
mkdir build
|
|
cd build
|
|
cmake ../rlottie
|
|
make -j
|
|
sudo make install
|
|
|
|
And finally add the ``-lrlottie`` flag to your linker.
|
|
|
|
On embedded systems you need to take care of integrating Rlottie to the
|
|
given build system.
|
|
|
|
ESP-IDF example at bottom
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
.. _rlottie_usage:
|
|
|
|
Usage
|
|
-----
|
|
|
|
You can use animation from files or raw data (text). In either case
|
|
first you need to enable :c:macro:`LV_USE_RLOTTIE` in ``lv_conf.h``.
|
|
|
|
The ``width`` and ``height`` of the object be set in the *create*
|
|
function and the animation will be scaled accordingly.
|
|
|
|
Use Rlottie from file
|
|
~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
To create a Lottie animation from file use:
|
|
|
|
.. code:: c
|
|
|
|
lv_obj_t * lottie = lv_rlottie_create_from_file(parent, width, height, "path/to/lottie.json");
|
|
|
|
Note that, Rlottie uses the standard STDIO C file API, so you can use
|
|
the path "normally" and no LVGL specific driver letter is required.
|
|
|
|
Use Rlottie from raw string data
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
``lv_example_rlottie_approve.c`` contains an example animation in raw
|
|
format. Instead storing the JSON string, a hex array is stored for the
|
|
following reasons:
|
|
|
|
- avoid escaping ``"`` character in the JSON file
|
|
- some compilers don't support very long strings
|
|
|
|
``lvgl/scripts/filetohex.py`` can be used to convert a Lottie file a hex
|
|
array. E.g.:
|
|
|
|
.. code:: shell
|
|
|
|
./filetohex.py path/to/lottie.json > out.txt
|
|
|
|
To create an animation from raw data:
|
|
|
|
.. code:: c
|
|
|
|
extern const uint8_t lottie_data[];
|
|
lv_obj_t* lottie = lv_rlottie_create_from_raw(parent, width, height, (const char *)lottie_data);
|
|
|
|
Getting animations
|
|
------------------
|
|
|
|
Lottie is standard and popular format so you can find many animation
|
|
files on the web. For example: https://lottiefiles.com/
|
|
|
|
You can also create your own animations with Adobe After Effects or
|
|
similar software.
|
|
|
|
Controlling animations
|
|
----------------------
|
|
|
|
LVGL provides two functions to control the animation mode:
|
|
:cpp:func:`lv_rlottie_set_play_mode` and :cpp:func:`lv_rlottie_set_current_frame`.
|
|
You'll combine your intentions when calling the first method, like in
|
|
these examples:
|
|
|
|
.. code:: c
|
|
|
|
lv_obj_t * lottie = lv_rlottie_create_from_file(scr, 128, 128, "test.json");
|
|
lv_obj_center(lottie);
|
|
// Pause to a specific frame
|
|
lv_rlottie_set_current_frame(lottie, 50);
|
|
lv_rlottie_set_play_mode(lottie, LV_RLOTTIE_CTRL_PAUSE); // The specified frame will be displayed and then the animation will pause
|
|
|
|
// Play backward and loop
|
|
lv_rlottie_set_play_mode(lottie, LV_RLOTTIE_CTRL_PLAY | LV_RLOTTIE_CTRL_BACKWARD | LV_RLOTTIE_CTRL_LOOP);
|
|
|
|
// Play forward once (no looping)
|
|
lv_rlottie_set_play_mode(lottie, LV_RLOTTIE_CTRL_PLAY | LV_RLOTTIE_CTRL_FORWARD);
|
|
|
|
The default animation mode is **play forward with loop**.
|
|
|
|
If you don't enable looping, a :cpp:enumerator:`LV_EVENT_READY` is sent when the
|
|
animation can not make more progress without looping.
|
|
|
|
To get the number of frames in an animation or the current frame index,
|
|
you can cast the :c:struct:`lv_obj_t` instance to a :c:struct:`lv_rlottie_t` instance
|
|
and inspect the ``current_frame`` and ``total_frames`` members.
|
|
|
|
ESP-IDF Example
|
|
---------------
|
|
|
|
Background
|
|
~~~~~~~~~~
|
|
|
|
Rlottie can be expensive to render on embedded hardware. Lottie
|
|
animations tend to use a large amount of CPU time and can use large
|
|
portions of RAM. This will vary from lottie to lottie but in general for
|
|
best performance:
|
|
|
|
- Limit total # of frames in the animation
|
|
- Where possible, try to avoid bezier type animations
|
|
- Limit animation render size
|
|
|
|
If your ESP32 chip does not have SPIRAM you will face severe limitations
|
|
in render size.
|
|
|
|
To give a better idea on this, lets assume you want to render a 240x320
|
|
lottie animation.
|
|
|
|
In order to pass initialization of the lv_rlottie_t object, you need
|
|
240x320x32/8 (307k) available memory. The latest ESP32-S3 has 256kb RAM
|
|
available for this (before freeRtos and any other initialization starts
|
|
taking chunks out). So while you can probably start to render a 50x50
|
|
animation without SPIRAM, PSRAM is highly recommended.
|
|
|
|
Additionally, while you might be able to pass initialization of the
|
|
lv_rlottie_t object, as rlottie renders frame to frame, this consumes
|
|
additional memory. A 30 frame animation that plays over 1 second
|
|
probably has minimal issues, but a 300 frame animation playing over 10
|
|
seconds could very easily crash due to lack of memory as rlottie
|
|
renders, depending on the complexity of the animation.
|
|
|
|
Rlottie will not compile for the IDF using the ``-02`` compiler option at
|
|
this time.
|
|
|
|
For stability in lottie animations, I found that they run best in the
|
|
IDF when enabling :c:macro:`LV_MEM_CUSTOM` (using ``stdlib.h``)
|
|
|
|
For all its faults, when running right-sized animations, they provide a
|
|
wonderful utility to LVGL on embedded LCDs and can look really good when
|
|
done properly.
|
|
|
|
When picking/designing a lottie animation consider the following
|
|
limitations:
|
|
|
|
- Build the lottie animation to be sized for the intended size
|
|
- it can scale/resize, but performance will be best when the base lottie size is as intended
|
|
- Limit total number of frames, the longer the lottie animation is,
|
|
the more memory it will consume for rendering (rlottie consumes IRAM for rendering)
|
|
- Build the lottie animation for the intended frame rate
|
|
- default lottie is 60fps, embedded LCDs likely won't go above 30fps
|
|
|
|
IDF Setup
|
|
~~~~~~~~~
|
|
|
|
Where the LVGL simulator uses the installed rlottie lib, the IDF works
|
|
best when using rlottie as a submodule under the components directory.
|
|
|
|
.. code:: shell
|
|
|
|
cd 'your/project/directory'
|
|
git add submodule
|
|
git add submodule https://github.com/Samsung/rlottie.git ./components/rlottie/rlottie
|
|
git submodule update --init --recursive
|
|
|
|
Now, Rlottie is available as a component in the IDF, but it requires
|
|
some additional changes and a CMakeLists file to tell the IDF how to
|
|
compile.
|
|
|
|
Rlottie patch file
|
|
~~~~~~~~~~~~~~~~~~
|
|
|
|
Rlottie relies on a dynamic linking for an image loader lib. This needs
|
|
to be disabled as the IDF doesn't play nice with dynamic linking.
|
|
|
|
A patch file is available in lvgl under:
|
|
``/env_support/esp/rlottie/0001-changes-to-compile-with-esp-idf.patch``
|
|
|
|
Apply the patch file to your rlottie submodule.
|
|
|
|
CMakeLists for IDF
|
|
~~~~~~~~~~~~~~~~~~
|
|
|
|
An example CMakeLists file has been provided at
|
|
``/env_support/esp/rlottie/CMakeLists.txt``
|
|
|
|
Copy this CMakeLists file to
|
|
``'your-project-directory'/components/rlottie/``
|
|
|
|
In addition to the component CMakeLists file, you'll also need to tell
|
|
your project level CMakeLists in your IDF project to require rlottie:
|
|
|
|
.. code:: console
|
|
|
|
REQUIRES "lvgl" "rlottie"
|
|
|
|
From here, you should be able to use lv_rlottie objects in your ESP-IDF
|
|
project as any other widget in LVGL ESP examples. Please remember that
|
|
these animations can be highly resource constrained and this does not
|
|
guarantee that every animation will work.
|
|
|
|
Additional Rlottie considerations in ESP-IDF
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
While unnecessary, removing the ``rlottie/rlottie/example`` folder can remove
|
|
many un-needed files for this embedded LVGL application
|
|
|
|
From here, you can use the relevant LVGL lv_rlottie functions to create
|
|
lottie animations in LVGL on embedded hardware!
|
|
|
|
Please note, that while lottie animations are capable of running on many
|
|
ESP chips, below is recommended for best performance.
|
|
|
|
- ESP32-S3-WROOM-1-N16R8
|
|
|
|
- 16mb quad spi flash
|
|
- 8mb octal spi PSRAM
|
|
|
|
- IDF4.4 or higher
|
|
|
|
The Esp-box devkit meets this spec and
|
|
https://github.com/espressif/esp-box is a great starting point to adding
|
|
lottie animations.
|
|
|
|
You will need to enable :c:macro:`LV_USE_RLOTTIE` through **idf.py** menuconfig under
|
|
LVGL component settings.
|
|
|
|
Additional changes to make use of SPIRAM
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
:cpp:expr:`lv_alloc/realloc` do not make use of SPIRAM. Given the high memory usage
|
|
of lottie animations, it is recommended to shift as much out of internal
|
|
DRAM into SPIRAM as possible. In order to do so, SPIRAM will need to be
|
|
enabled in the menuconfig options for your given espressif chip.
|
|
|
|
There may be a better solution for this, but for the moment the
|
|
recommendation is to make local modifications to the lvgl component in
|
|
your espressif project. This is as simple as swapping
|
|
:cpp:expr:`lv_alloc/lv_realloc` calls in `lv_rlottie.c`` with :cpp:expr:`heap_caps_malloc` (for
|
|
IDF) with the appropriate :cpp:expr:`MALLOC_CAP` call - for SPIRAM usage this is
|
|
:cpp:expr:`MALLOC_CAP_SPIRAM`.
|
|
|
|
.. code:: c
|
|
|
|
rlottie->allocated_buf = heap_caps_malloc(allocated_buf_size+1, MALLOC_CAP_SPIRAM);
|
|
|
|
.. _rlottie_example:
|
|
|
|
Example
|
|
-------
|
|
|
|
.. include:: ../examples/libs/rlottie/index.rst
|
|
|
|
.. _rlottie_api:
|
|
|
|
API
|
|
---
|