1.源文件准备
(1)获取源代码
由于很多人不满足gif文件在lvgl播放下占用大量的flash内存,今天我们来讲解一下怎么为esp32的两种框架esp-idf ,arduino-platformio实现rlottie 动画的播放。
首先我参考b站up@西瓜杨桃的视频讲解,他提供了主要的思路和步骤,我也是通过复现他的过程中发现了很多问题和逐步解决这些问题的。
首先我们来到github找到三星的这个rlottie库,分支中选择c++11和工具链选择esp-idf4.4.6 powershell才能够成功编译,编译完生成的静态库适用于5.2以下的版本,更高的版本还没有测试过的。使用这样的选择能解决因为posix标准系统带来的文件问题,不过我也不清楚是否比起c++14版本是否会有性能下降等情况。https://github.com/Samsung/rlottie
我们下载下来这个zip,随后会使用这个文件。
(2)查找esp工具链
使用everthing软件查找toolchain-esp32s3.cmake,一定要是4.4.6版本
你需要安装一个esp-idf 4.4.6的powershell具体怎么安装请自行网上查找,然后找到他,打开准备用于编译。一定要是4.4.6版本
最好使用你的编译环境下的工具链,不过本质上一样的
2.编译
(1)CMake
创建一个文件夹,构建如下的结构树,将解压出来的源代码改名为rlottie放入这个文件夹
修改CMakeLists.txt为一下内容
cmake_minimum_required(VERSION 3.14)
Set(LOTTIE_MODULE OFF)
Set(LOTTIE_THREAD OFF)
Set(BUILD_SHARED_LIBS OFF)
set(LOTTIE_EXAMPLE OFF)
add_definitions(-DESP_PLATFORM)
add_subdirectory(rlottie)
(2)为源文件打上esp的补丁
From 18083a559734d297838e4cf34a856a4770062319 Mon Sep 17 00:00:00 2001
From: tvanfossen <vanfosst@gmail.com>
Date: Tue, 23 Aug 2022 10:06:53 -0400
Subject: [PATCH] changes to compile with esp-idf
---
CMakeLists.txt | 11 ++++++-----
src/vector/vimageloader.cpp | 23 +++++++++++++----------
2 files changed, 19 insertions(+), 15 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 38a9862..ee6d2cd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -95,10 +95,11 @@ if (NOT APPLE AND NOT WIN32)
)
endif()
-if (LOTTIE_MODULE)
- # for dlopen, dlsym and dlclose dependency
- target_link_libraries(rlottie PRIVATE ${CMAKE_DL_LIBS})
-endif()
+# No Sym links in ESP-IDF
+# if (LOTTIE_MODULE)
+# # for dlopen, dlsym and dlclose dependency
+# target_link_libraries(rlottie PRIVATE ${CMAKE_DL_LIBS})
+# endif()
if (NOT LOTTIE_ASAN)
if(APPLE)
@@ -137,7 +138,7 @@ endif (NOT LIB_INSTALL_DIR)
#declare source and include files
add_subdirectory(inc)
add_subdirectory(src)
-add_subdirectory(example)
+# add_subdirectory(example) // We dont need example dir in ESP-IDF
if (LOTTIE_TEST)
enable_testing()
diff --git a/src/vector/vimageloader.cpp b/src/vector/vimageloader.cpp
index c2446be..3df4c6a 100644
--- a/src/vector/vimageloader.cpp
+++ b/src/vector/vimageloader.cpp
@@ -6,7 +6,7 @@
#ifdef _WIN32
# include <windows.h>
#else
-# include <dlfcn.h>
+// # include <dlfcn.h> //Does not work on ESP-IDF
#endif // _WIN32
using lottie_image_load_f = unsigned char *(*)(const char *filename, int *x,
@@ -61,22 +61,25 @@ struct VImageLoader::Impl {
void *dl_handle{nullptr};
void init()
{
- imageLoad = reinterpret_cast<lottie_image_load_f>(
- dlsym(dl_handle, "lottie_image_load"));
- imageFree = reinterpret_cast<lottie_image_free_f>(
- dlsym(dl_handle, "lottie_image_free"));
- imageFromData = reinterpret_cast<lottie_image_load_data_f>(
- dlsym(dl_handle, "lottie_image_load_from_data"));
+ // No sym links in ESP-iDF
+ // imageLoad = reinterpret_cast<lottie_image_load_f>(
+ // dlsym(dl_handle, "lottie_image_load"));
+ // imageFree = reinterpret_cast<lottie_image_free_f>(
+ // dlsym(dl_handle, "lottie_image_free"));
+ // imageFromData = reinterpret_cast<lottie_image_load_data_f>(
+ // dlsym(dl_handle, "lottie_image_load_from_data"));
}
void moduleFree()
{
- if (dl_handle) dlclose(dl_handle);
+ // if (dl_handle) dlclose(dl_handle); // No sym links in ESP-iDF
}
bool moduleLoad()
{
- dl_handle = dlopen(LOTTIE_IMAGE_MODULE_PLUGIN, RTLD_LAZY);
- return (dl_handle == nullptr);
+ // No sym links in ESP idf
+ // dl_handle = dlopen(LOTTIE_IMAGE_MODULE_PLUGIN, RTLD_LAZY);
+ // return (dl_handle == nullptr);
+ return true
}
# endif // _WIN32
#else // LOTTIE_IMAGE_MODULE_SUPPORT
--
2.34.1
指导一下如何找到这些文件,首先是rlottie下的cmakelists.txt,直接复制我已经修改好的cmakelists内容进去
cmake_minimum_required( VERSION 3.3 )
#declare project
project( rlottie VERSION 0.0.1 LANGUAGES C CXX ASM)if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE MinSizeRel)
endif()if (NOT DEFINED BUILD_SHARED_LIBS)
# Keep the previous behavior of the build system, consistent with Meson.
set(BUILD_SHARED_LIBS ON)
endif()#declare target
add_library( rlottie )
set_target_properties( rlottie PROPERTIES DEFINE_SYMBOL LOT_BUILD )#declare version of the target
set(player_version_major 0)
set(player_version_minor 0)
set(player_version_patch 1)
set(player_version ${player_version_major}.${player_version_minor}.${player_version_patch} )
set_target_properties(rlottie PROPERTIES
VERSION ${player_version}
SOVERSION ${player_version_major}
)#declare alias so that library can be used inside the build tree, e.g. when testing
add_library(rlottie::rlottie ALIAS rlottie)option(LOTTIE_MODULE "Enable LOTTIE MODULE SUPPORT" OFF)
option(LOTTIE_THREAD "Enable LOTTIE THREAD SUPPORT" OFF)
option(LOTTIE_CACHE "Enable LOTTIE CACHE SUPPORT" ON)
option(LOTTIE_TEST "Build LOTTIE AUTOTESTS" OFF)
option(LOTTIE_CCACHE "Enable LOTTIE ccache SUPPORT" OFF)
option(LOTTIE_ASAN "Compile with asan" OFF)set(LOTTIE_MODULE_PATH "${CMAKE_SHARED_LIBRARY_PREFIX}rlottie-image-loader${CMAKE_SHARED_LIBRARY_SUFFIX}"
CACHE STRING "Absolute or relative path to dynamic loader plugin.")configure_file(${CMAKE_CURRENT_LIST_DIR}/cmake/config.h.in config.h)
target_include_directories(rlottie
PRIVATE
"${CMAKE_CURRENT_BINARY_DIR}"
)#declare target compilation options
target_compile_options(rlottie
PUBLIC
PRIVATE
-std=c++11
-fno-exceptions
-fno-unwind-tables
-fno-asynchronous-unwind-tables
-fno-rtti
-Wall
-Werror
-Wextra
-Wnon-virtual-dtor
-Woverloaded-virtual
-Wno-unused-parameter
-fvisibility=hidden
)#declare dependancy
set( CMAKE_THREAD_PREFER_PTHREAD TRUE )
find_package( Threads )target_link_libraries(rlottie
PUBLIC
"${CMAKE_THREAD_LIBS_INIT}"
)if (NOT APPLE AND NOT WIN32)
target_link_libraries(rlottie
PRIVATE
"-Wl,--version-script=${CMAKE_SOURCE_DIR}/rlottie.expmap"
)
endif()# No Sym links in ESP-IDF
# if (LOTTIE_MODULE)
# # for dlopen, dlsym and dlclose dependency
# target_link_libraries(rlottie PRIVATE ${CMAKE_DL_LIBS})
# endif()if (NOT LOTTIE_ASAN)
if(APPLE)
target_link_libraries(rlottie
PUBLIC
"-Wl, -undefined error"
)
else()
target_link_libraries(rlottie
PUBLIC
"-Wl,--no-undefined"
)
endif()
endif()if (LOTTIE_CCACHE)
find_program(CCACHE_FOUND ccache)
if (CCACHE_FOUND)
message(STATUS "Found ccache")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
else()
message(STATUS "Could NOT find ccache (this is NOT an error)")
endif()
endif()if (LOTTIE_ASAN)
target_compile_options(rlottie PUBLIC -fsanitize=address)
target_link_options(rlottie PUBLIC -fsanitize=address)
endif()if (NOT LIB_INSTALL_DIR)
set (LIB_INSTALL_DIR "/usr/lib")
endif (NOT LIB_INSTALL_DIR)#declare source and include files
add_subdirectory(inc)
add_subdirectory(src)
# add_subdirectory(example)# if (LOTTIE_TEST)
# enable_testing()
# add_subdirectory(test)
# endif()SET(PREFIX ${CMAKE_INSTALL_PREFIX})
SET(EXEC_DIR ${PREFIX})
SET(LIBDIR ${LIB_INSTALL_DIR})
SET(INCDIR ${PREFIX}/include)CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
#install header
install(FILES
inc/rlottie.h
inc/rlottie_capi.h
inc/rlottiecommon.h
DESTINATION include)#install lib
install( TARGETS rlottie EXPORT rlottie-targets
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
INCLUDES DESTINATION include
)#install config file.
install( EXPORT rlottie-targets
FILE rlottieTargets.cmake
NAMESPACE rlottie::
DESTINATION ${LIB_INSTALL_DIR}/cmake/rlottie
)
#Create a ConfigVersion.cmake file
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/rlottieConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY AnyNewerVersion
)configure_package_config_file(${CMAKE_CURRENT_LIST_DIR}/cmake/rlottieConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/rlottieConfig.cmake
INSTALL_DESTINATION ${LIB_INSTALL_DIR}/cmake/rlottie
)#Install the config, configversion and custom find modules
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/rlottieConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/rlottieConfigVersion.cmake
DESTINATION ${LIB_INSTALL_DIR}/cmake/rlottie
)
export(EXPORT rlottie-targets FILE ${CMAKE_CURRENT_BINARY_DIR}/rlottieTargets.cmake NAMESPACE rlottie::)#Register package in user's package registry
export(PACKAGE rlottie)
rlottie/src/vector/vimageloader.cpp这个文件中将这些代码屏蔽掉
找到\rlottie\src\binding\c\lottieanimation_capi.cpp这个文件为其添加strdup方法的定义如下图所示
#ifdef ESP_PLATFORM
extern "C" {
#include <string>
char* strdup(const char* str);
}
#endif
最后将rlottie/example文件夹直接删掉,否则会无法通过编译,这样我们就打好了补丁。
(3)获取静态库
保存文件,然后打开esp-idf powershell,进入到示例目录下
cd "D:\lv_lib_lottie\rlottie_lib\build"
将我们在开头找到的工具链地址复制进下面的命令里去。一定要是4.4.6版本
cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE="你查找到的toolchain-esp32s3.cmake地址"
然后就会开始编译
成功编译是这样的,然后使用以下命令使用ninja生成静态库
ninja
这样就成功获取了静态库librlottie.a文件在D:\lv_lib_lottie\rlottie_lib\build\rlottie目录下
3.将静态库链接到项目中
(1)platformio实现
编写platformio.ini,添加以下代码
lib_extra_dirs=
"D:/lv_lib_lottie/rlottie_lib/build/rlottie" #此处为存放静态库librlottie.a文件处
build_flags =
-L"D://lv_lib_lottie/rlottie_lib/build2/rlottie"
-lrlottie
-I"D:/FirmwareS3/lib/lvgl/src/extra/libs/rlottie" #你项目中lvgl的文件地址\lib\lvgl\src\extra\libs\rlottie
D:\lv_lib_lottie\rlottie_lib\rlottie\inc目录下找到rlottie_capi.h和rlottiecommon.h这两个文件复制到
你的项目地址\lvgl\src\extra\libs\rlottie下
打开lv_rlottie.c确保rlottie_capi.h是这样添加头文件的
/**
* @file lv_rlottie.c
*
*/
#include "esp_heap_caps.h"
/*********************
* INCLUDES
*********************/
#include "lv_rlottie.h"
#if LV_USE_RLOTTIE
#include "rlottie_capi.h"
/*********************
* DEFINES
*********************/
#define MY_CLASS &lv_rlottie_class
rlottie_capi.h中开头这样添加头文件
/*
* Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _RLOTTIE_CAPI_H_
#define _RLOTTIE_CAPI_H_
#include <stddef.h>
#include <stdint.h>
#include "rlottiecommon.h"
这样就完成了静态库的链接了。
(2)idf实现
参考使用 ESP-IDF 生成第三方的 .a 静态库并使用的流程_idf 创建并生成.a-CSDN博客为idf添加rlottie.a 的实现
首先在components下新建rlottie文件夹,结构树如下
components/
└── rlottie/
├── include/
│ ├── rlottie_capi.h
│ └── rlottiecommon.h
├── CMakeLists.txt
└── librlottie.a
cmakelists.txt如下编写
idf_component_register(INCLUDE_DIRS "./include")
target_link_libraries(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_LIST_DIR}/librlottie.a")
这样你就可以在文件内调用 rlottie_capi.h和rlottiecommon.h中的api了
无论是在哪中框架下都不要忘记在lv_conf.h中开启lottie player
/*Rlottie library*/
#define LV_USE_RLOTTIE 1
4.ESP32 S3的特定优化
为lottie动画分配缓冲代码如下 ,我们可以很明显看出一个80*80像素的lottie动画就需要25kb的内部ram,这是我们无法接受的尤其是你的lvgl已经分配一块不小的缓存。
size_t allocaled_buf_size = (create_width * create_height * LV_ARGB32 / 8);
所以我们修改这个代码让其在psram中分配缓冲区
#include "esp_heap_caps.h" //文件顶部进行头文件包含
static void lv_rlottie_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
{
LV_UNUSED(class_p);
lv_rlottie_t * rlottie = (lv_rlottie_t *) obj;
if(rlottie_desc_create) {
rlottie->animation = lottie_animation_from_data(rlottie_desc_create, rlottie_desc_create, "");
}
else if(path_create) {
rlottie->animation = lottie_animation_from_file(path_create);
}
if(rlottie->animation == NULL) {
LV_LOG_WARN("The aniamtion can't be opened");
return;
}
rlottie->total_frames = lottie_animation_get_totalframe(rlottie->animation);
rlottie->framerate = (size_t)lottie_animation_get_framerate(rlottie->animation);
rlottie->current_frame = 0;
rlottie->scanline_width = create_width * LV_ARGB32 / 8;
size_t allocaled_buf_size = (create_width * create_height * LV_ARGB32 / 8);
rlottie->allocated_buf = heap_caps_malloc(allocaled_buf_size + 1, MALLOC_CAP_SPIRAM);
if(rlottie->allocated_buf == NULL) {
LV_LOG_WARN("Memory allocation failed");
return;
}
if(rlottie->allocated_buf != NULL) {
rlottie->allocated_buffer_size = allocaled_buf_size;
memset(rlottie->allocated_buf, 0, allocaled_buf_size);
}
rlottie->imgdsc.header.always_zero = 0;
rlottie->imgdsc.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
rlottie->imgdsc.header.h = create_height;
rlottie->imgdsc.header.w = create_width;
rlottie->imgdsc.data = (void *)rlottie->allocated_buf;
rlottie->imgdsc.data_size = allocaled_buf_size;
lv_img_set_src(obj, &rlottie->imgdsc);
rlottie->play_ctrl = LV_RLOTTIE_CTRL_FORWARD | LV_RLOTTIE_CTRL_PLAY | LV_RLOTTIE_CTRL_LOOP;
rlottie->dest_frame = rlottie->total_frames; /* invalid destination frame so it's possible to pause on frame 0 */
rlottie->task = lv_timer_create(next_frame_task_cb, 1000 / rlottie->framerate, obj);
lv_obj_update_layout(obj);
}
将原先的 static void lv_rlottie_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)替换为我修改过的代码这样你就可以轻松创建一个150*150的lottie动画
示例如下
#include <lvgl>
const char lodingani[] = "{\"nm\":\"Main Scene\",\"ddd\":0,\"h\":500,\"w\":500,\"meta\":{\"g\":\"@lottiefiles/creator 1.15.0\"},\"layers\":[{\"ty\":4,\"nm\":\"Ellipse 1\",\"sr\":1,\"st\":0,\"op\":120,\"ip\":0,\"hd\":false,\"ddd\":0,\"bm\":0,\"hasMask\":false,\"ao\":0,\"ks\":{\"a\":{\"a\":0,\"k\":[0,0]},\"s\":{\"a\":0,\"k\":[80,80]},\"sk\":{\"a\":0,\"k\":0},\"p\":{\"a\":0,\"k\":[246,247]},\"r\":{\"a\":1,\"k\":[{\"o\":{\"x\":0,\"y\":0},\"i\":{\"x\":1,\"y\":1},\"s\":[160],\"t\":0},{\"s\":[-200],\"t\":119}]},\"sa\":{\"a\":0,\"k\":0},\"o\":{\"a\":0,\"k\":100}},\"ef\":[],\"shapes\":[{\"ty\":\"sh\",\"bm\":0,\"hd\":false,\"nm\":\"Ellipse Path 1\",\"d\":1,\"ks\":{\"a\":0,\"k\":{\"c\":true,\"i\":[[-73.9546,0],[0,-73.9546],[73.9546,0],[0,73.9546]],\"o\":[[73.9546,0],[0,73.9546],[-73.9546,0],[0,-73.9546]],\"v\":[[0,-134],[134,0],[0,134],[-134,0]]}}},{\"ty\":\"tm\",\"bm\":0,\"hd\":false,\"nm\":\"Trim Path\",\"e\":{\"a\":1,\"k\":[{\"o\":{\"x\":0.65,\"y\":0},\"i\":{\"x\":0.36,\"y\":1},\"s\":[100],\"t\":4},{\"s\":[0],\"t\":120}]},\"o\":{\"a\":0,\"k\":0},\"s\":{\"a\":1,\"k\":[{\"o\":{\"x\":0.55,\"y\":0.06},\"i\":{\"x\":0.36,\"y\":1},\"s\":[100],\"t\":0},{\"s\":[0],\"t\":116}]},\"m\":1},{\"ty\":\"st\",\"bm\":0,\"hd\":false,\"nm\":\"Stroke\",\"lc\":2,\"lj\":2,\"ml\":1,\"o\":{\"a\":0,\"k\":100},\"w\":{\"a\":0,\"k\":28},\"c\":{\"a\":0,\"k\":[0,0.8667,0.702,1]}}],\"ind\":1},{\"ty\":4,\"nm\":\"Ellipse 1\",\"sr\":1,\"st\":0,\"op\":120,\"ip\":0,\"hd\":false,\"ddd\":0,\"bm\":0,\"hasMask\":false,\"ao\":0,\"ks\":{\"a\":{\"a\":0,\"k\":[0,0]},\"s\":{\"a\":0,\"k\":[80,80]},\"sk\":{\"a\":0,\"k\":0},\"p\":{\"a\":0,\"k\":[246,247]},\"r\":{\"a\":1,\"k\":[{\"o\":{\"x\":0,\"y\":0},\"i\":{\"x\":1,\"y\":1},\"s\":[60],\"t\":0},{\"s\":[-300],\"t\":119}]},\"sa\":{\"a\":0,\"k\":0},\"o\":{\"a\":0,\"k\":100}},\"ef\":[],\"shapes\":[{\"ty\":\"sh\",\"bm\":0,\"hd\":false,\"nm\":\"Ellipse Path 1\",\"d\":1,\"ks\":{\"a\":0,\"k\":{\"c\":true,\"i\":[[-73.9546,0],[0,-73.9546],[73.9546,0],[0,73.9546]],\"o\":[[73.9546,0],[0,73.9546],[-73.9546,0],[0,-73.9546]],\"v\":[[0,-134],[134,0],[0,134],[-134,0]]}}},{\"ty\":\"tm\",\"bm\":0,\"hd\":false,\"nm\":\"Trim Path\",\"e\":{\"a\":1,\"k\":[{\"o\":{\"x\":0.65,\"y\":0},\"i\":{\"x\":0.36,\"y\":1},\"s\":[100],\"t\":26},{\"s\":[0],\"t\":120}]},\"o\":{\"a\":0,\"k\":0},\"s\":{\"a\":1,\"k\":[{\"o\":{\"x\":0.55,\"y\":0.06},\"i\":{\"x\":0.36,\"y\":1},\"s\":[100],\"t\":0},{\"s\":[0],\"t\":96}]},\"m\":1},{\"ty\":\"st\",\"bm\":0,\"hd\":false,\"nm\":\"Stroke\",\"lc\":2,\"lj\":2,\"ml\":1,\"o\":{\"a\":0,\"k\":100},\"w\":{\"a\":0,\"k\":28},\"c\":{\"a\":0,\"k\":[0,0.8667,0.702,1]}}],\"ind\":2},{\"ty\":4,\"nm\":\"Ellipse 1\",\"sr\":1,\"st\":0,\"op\":122,\"ip\":0,\"hd\":false,\"ddd\":0,\"bm\":0,\"hasMask\":false,\"ao\":0,\"ks\":{\"a\":{\"a\":0,\"k\":[0,0]},\"s\":{\"a\":0,\"k\":[100,100]},\"sk\":{\"a\":0,\"k\":0},\"p\":{\"a\":0,\"k\":[246,247]},\"r\":{\"a\":1,\"k\":[{\"o\":{\"x\":0,\"y\":0},\"i\":{\"x\":1,\"y\":1},\"s\":[0],\"t\":0},{\"s\":[-359],\"t\":120}]},\"sa\":{\"a\":0,\"k\":0},\"o\":{\"a\":0,\"k\":100}},\"ef\":[],\"shapes\":[{\"ty\":\"sh\",\"bm\":0,\"hd\":false,\"nm\":\"Ellipse Path 1\",\"d\":1,\"ks\":{\"a\":0,\"k\":{\"c\":true,\"i\":[[-73.9546,0],[0,-73.9546],[73.9546,0],[0,73.9546]],\"o\":[[73.9546,0],[0,73.9546],[-73.9546,0],[0,-73.9546]],\"v\":[[0,-134],[134,0],[0,134],[-134,0]]}}},{\"ty\":\"tm\",\"bm\":0,\"hd\":false,\"nm\":\"Trim Path\",\"e\":{\"a\":1,\"k\":[{\"o\":{\"x\":0.65,\"y\":0},\"i\":{\"x\":0.36,\"y\":1},\"s\":[100],\"t\":26},{\"s\":[0],\"t\":120}]},\"o\":{\"a\":0,\"k\":0},\"s\":{\"a\":1,\"k\":[{\"o\":{\"x\":0.55,\"y\":0.06},\"i\":{\"x\":0.36,\"y\":1},\"s\":[100],\"t\":0},{\"s\":[0],\"t\":96}]},\"m\":1},{\"ty\":\"st\",\"bm\":0,\"hd\":false,\"nm\":\"Stroke\",\"lc\":2,\"lj\":2,\"ml\":1,\"o\":{\"a\":0,\"k\":100},\"w\":{\"a\":0,\"k\":10},\"c\":{\"a\":0,\"k\":[0.8992,0.9808,0.9658,1]}}],\"ind\":3}],\"v\":\"5.7.0\",\"fr\":60,\"op\":120,\"ip\":0,\"assets\":[]}";
void ui_ainimation_screen_init(void){
lottie_screen = lv_obj_create(NULL);
lv_obj_clear_flag(lottie_screen, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_style_bg_color(lottie_screen, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_opa(lottie_screen, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_disp_load_scr(lottie_screen);
// 初始化 Lottie 动画
lottie_obj = lv_rlottie_create_from_raw(lottie_screen, 150, 150, lodingani);
lv_obj_center(lottie_obj);
}
void setup()
{
ui_ainimation_screen_init();
}
void loop()
{
lv_timer_handler(); // 处理LVGL任务
}
tips:我设置了1024 * 30大小的堆栈用于lottie动画播放,lottie动画的json文件大于15kb就很难渲染成功,不知道为什么,可能是算力不够,我的刷新率太高