lvgl 动画设计
一、重要接口
void lv_anim_init(lv_anim_t * a):
对一个lv_anim_t
类型的变量进行初始化。在使用动画之前,需要先调用此函数来初始化动画变量。void lv_anim_set_var(lv_anim_t * a, void * var)
:设置要进行动画处理的变量。void lv_anim_set_exec_cb(lv_anim_t * a, lv_anim_exec_xcb_t exec_cb)
:设定在动画过程中要执行的函数。这个函数会在动画的每个步骤中被调用,用来更新变量的值。void lv_anim_set_time(lv_anim_t * a, uint32_t duration)
:设置动画的持续时间(以毫秒为单位)。void lv_anim_set_delay(lv_anim_t * a, uint32_t delay)
:设置动画开始前的延迟时间(以毫秒为单位)。void lv_anim_set_values(lv_anim_t * a, int32_t start, int32_t end)
:设置动画的起始值和结束值void lv_anim_set_custom_exec_cb(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb)
:与lv_anim_set_exec_cb
类似,但lv_anim_custom_exec_cb_t
接收lv_anim_t *
作为第一个参数。void lv_anim_set_path_cb(lv_anim_t * a, lv_anim_path_cb_t path_cb)
:设置动画的路径(曲线)。不同的路径函数会产生不同的动画效果,例如线性、缓入、缓出等。void lv_anim_set_start_cb(lv_anim_t * a, lv_anim_start_cb_t start_cb)
:设置动画真正开始时(考虑延迟)要调用的函数。void lv_anim_set_get_value_cb(lv_anim_t * a, lv_anim_get_value_cb_t get_value_cb)
:设置一个函数,该函数用于获取变量的当前值,并使起始值和结束值相对于返回的当前值。void lv_anim_set_ready_cb(lv_anim_t * a, lv_anim_ready_cb_t ready_cb)
:设置动画完成时要调用的函数。void lv_anim_set_playback_time(lv_anim_t * a, uint32_t time)
:使动画在正向播放完成后进行反向播放,并设置反向播放的持续时间。若time
为 0,则禁用反向播放。void lv_anim_set_playback_delay(lv_anim_t * a, uint32_t delay)
:设置动画反向播放开始前的延迟时间。void lv_anim_set_repeat_count(lv_anim_t * a, uint16_t cnt)
:设置动画的重复次数。若cnt
为LV_ANIM_REPEAT_INFINITE
,则表示无限重复;若为 0,则禁用重复。void lv_anim_set_repeat_delay(lv_anim_t * a, uint32_t delay)
:设置动画每次重复开始前的延迟时间。void lv_anim_set_early_apply(lv_anim_t * a, bool en)
:设置动画的起始值是立即应用,还是在延迟时间结束后才应用。lv_anim_t * lv_anim_start(const lv_anim_t * a)
:创建并启动一个动画。uint32_t lv_anim_get_delay(lv_anim_t * a)
:获取动画开始前的延迟时间。uint32_t lv_anim_get_playtime(lv_anim_t * a)
:获取动画播放所需的时间。bool lv_anim_del(void * var, lv_anim_exec_xcb_t exec_cb)
:删除一个变量的指定动画执行函数的动画。若exec_cb
为NULL
,则删除该变量的所有动画。void lv_anim_del_all(void)
:删除所有动画。lv_anim_t * lv_anim_get(void * var, lv_anim_exec_xcb_t exec_cb)
:获取一个变量的指定动画执行函数的动画。若exec_cb
为NULL
,则返回第一个匹配var
的动画。bool lv_anim_custom_del(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb)
:通过从a
中获取动画变量来删除动画。只有具有exec_cb
的动画会被删除。lv_anim_t * lv_anim_custom_get(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb)
:获取一个变量的指定动画执行函数的动画。uint16_t lv_anim_count_running(void)
:获取当前正在运行的动画数量。uint32_t lv_anim_speed_to_time(uint32_t speed, int32_t start, int32_t end)
:根据给定的速度以及起始值和结束值,计算动画所需的时间。void lv_anim_refr_now(void)
:手动刷新动画的状态。在无法运行lv_timer_handler
的阻塞过程中,此函数可用于使动画继续运行。通常不应直接使用,因为它会在lv_refr_now()
中被调用。int32_t lv_anim_path_linear(const lv_anim_t * a)
:计算应用线性特性的动画的当前值。int32_t lv_anim_path_ease_in(const lv_anim_t * a)
:计算在起始阶段减速的动画的当前值。int32_t lv_anim_path_ease_out(const lv_anim_t * a)
:计算在结束阶段减速的动画的当前值。int32_t lv_anim_path_ease_in_out(const lv_anim_t * a)
:计算应用 “S” 特性(余弦)的动画的当前值。int32_t lv_anim_path_overshoot(const lv_anim_t * a)
:计算在结束时有过冲的动画的当前值。int32_t lv_anim_path_bounce(const lv_anim_t * a)
:计算有 3 次反弹的动画的当前值。int32_t lv_anim_path_step(const lv_anim_t * a)
:计算应用步进特性的动画的当前值(在动画结束时设置结束值)。
二、demo
static void anim_x_cb(void * var, int32_t v)
{lv_obj_set_x(var, v);
}static void sw_event_cb(lv_event_t * e)
{lv_obj_t * sw = lv_event_get_target(e);lv_obj_t * label = lv_event_get_user_data(e);if(lv_obj_has_state(sw, LV_STATE_CHECKED)) {lv_anim_t a;lv_anim_init(&a);lv_anim_set_var(&a, label);lv_anim_set_values(&a, lv_obj_get_x(label), 100);lv_anim_set_time(&a, 500);lv_anim_set_exec_cb(&a, anim_x_cb);lv_anim_set_path_cb(&a, lv_anim_path_overshoot);lv_anim_start(&a);} else {lv_anim_t a;lv_anim_init(&a);lv_anim_set_var(&a, label);lv_anim_set_values(&a, lv_obj_get_x(label), 0);lv_anim_set_time(&a, 500);lv_anim_set_exec_cb(&a, anim_x_cb);lv_anim_set_path_cb(&a, lv_anim_path_ease_in);lv_anim_start(&a);}}/*** Start animation on an event*/
static void lv_example_anim_1(void)
{lv_obj_t * label = lv_label_create(lv_scr_act());lv_label_set_text(label, "Hello animations!");lv_obj_set_pos(label, 100, 10);lv_obj_t * sw = lv_switch_create(lv_scr_act());lv_obj_center(sw);lv_obj_add_state(sw, LV_STATE_CHECKED);lv_obj_add_event_cb(sw, sw_event_cb, LV_EVENT_VALUE_CHANGED, label);
}
static void anim_x_cb(void * var, int32_t v)
{lv_obj_set_x(var, v);
}static void anim_size_cb(void * var, int32_t v)
{lv_obj_set_size(var, v, v);
}/*** Create a playback animation*/
void lv_example_anim_2(void)
{lv_obj_t * obj = lv_obj_create(lv_scr_act());lv_obj_set_style_bg_color(obj, lv_palette_main(LV_PALETTE_RED), 0);lv_obj_set_style_radius(obj, LV_RADIUS_CIRCLE, 0);lv_obj_align(obj, LV_ALIGN_LEFT_MID, 10, 0);lv_anim_t a;lv_anim_init(&a);lv_anim_set_var(&a, obj);lv_anim_set_values(&a, 10, 50);lv_anim_set_time(&a, 1000);lv_anim_set_playback_delay(&a, 100);lv_anim_set_playback_time(&a, 300);lv_anim_set_repeat_delay(&a, 500);lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);lv_anim_set_path_cb(&a, lv_anim_path_ease_in_out);lv_anim_set_exec_cb(&a, anim_size_cb);lv_anim_start(&a);lv_anim_set_exec_cb(&a, anim_x_cb);lv_anim_set_values(&a, 10, 240);lv_anim_start(&a);
}
/*** the example show the use of cubic-bezier3 in animation.* the control point P1,P2 of cubic-bezier3 can be adjusted by slider.* and the chart shows the cubic-bezier3 in real time. you can click* run button see animation in current point of cubic-bezier3.*/#define CHART_POINTS_NUM 256struct {lv_obj_t * anim_obj;lv_obj_t * chart;lv_chart_series_t * ser1;lv_obj_t * p1_slider;lv_obj_t * p1_label;lv_obj_t * p2_slider;lv_obj_t * p2_label;lv_obj_t * run_btn;uint16_t p1;uint16_t p2;lv_anim_t a;
} ginfo;static int32_t anim_path_bezier3_cb(const lv_anim_t * a);
static void refer_chart_cubic_bezier(void);
static void run_btn_event_handler(lv_event_t * e);
static void slider_event_cb(lv_event_t * e);
static void page_obj_init(lv_obj_t * par);
static void anim_x_cb(void * var, int32_t v);/*** create an animation*/
void lv_example_anim_3(void)
{static lv_coord_t col_dsc[] = {LV_GRID_FR(1), 200, LV_GRID_FR(1),LV_GRID_TEMPLATE_LAST};static lv_coord_t row_dsc[] = {30, 10, 10, LV_GRID_FR(1),LV_GRID_TEMPLATE_LAST};/*Create a container with grid*/lv_obj_t * cont = lv_obj_create(lv_scr_act());lv_obj_set_style_pad_all(cont, 2, LV_PART_MAIN);lv_obj_set_style_pad_column(cont, 10, LV_PART_MAIN);lv_obj_set_style_pad_row(cont, 10, LV_PART_MAIN);lv_obj_set_grid_dsc_array(cont, col_dsc, row_dsc);lv_obj_set_size(cont, 320, 240);lv_obj_center(cont);page_obj_init(cont);lv_anim_init(&ginfo.a);lv_anim_set_var(&ginfo.a, ginfo.anim_obj);int32_t end = lv_obj_get_style_width(cont, LV_PART_MAIN) -lv_obj_get_style_width(ginfo.anim_obj, LV_PART_MAIN) - 10;lv_anim_set_values(&ginfo.a, 5, end);lv_anim_set_time(&ginfo.a, 2000);lv_anim_set_exec_cb(&ginfo.a, anim_x_cb);lv_anim_set_path_cb(&ginfo.a, anim_path_bezier3_cb);refer_chart_cubic_bezier();
}static int32_t anim_path_bezier3_cb(const lv_anim_t * a)
{uint32_t t = lv_map(a->act_time, 0, a->time, 0, 1024);int32_t step = lv_bezier3(t, 0, ginfo.p1, ginfo.p2, 1024);int32_t new_value;new_value = step * (a->end_value - a->start_value);new_value = new_value >> 10;new_value += a->start_value;return new_value;
}static void refer_chart_cubic_bezier(void)
{for(uint16_t i = 0; i <= CHART_POINTS_NUM; i ++) {uint32_t t = i * (1024 / CHART_POINTS_NUM);int32_t step = lv_bezier3(t, 0, ginfo.p1, ginfo.p2, 1024);lv_chart_set_value_by_id2(ginfo.chart, ginfo.ser1, i, t, step);}lv_chart_refresh(ginfo.chart);
}static void anim_x_cb(void * var, int32_t v)
{lv_obj_set_style_translate_x(var, v, LV_PART_MAIN);
}static void run_btn_event_handler(lv_event_t * e)
{lv_event_code_t code = lv_event_get_code(e);if(code == LV_EVENT_CLICKED) {lv_anim_start(&ginfo.a);}
}static void slider_event_cb(lv_event_t * e)
{char buf[16];lv_obj_t * label;lv_obj_t * slider = lv_event_get_target(e);if(slider == ginfo.p1_slider) {label = ginfo.p1_label;ginfo.p1 = lv_slider_get_value(slider);lv_snprintf(buf, sizeof(buf), "p1:%d", ginfo.p1);}else {label = ginfo.p2_label;ginfo.p2 = lv_slider_get_value(slider);lv_snprintf(buf, sizeof(buf), "p2:%d", ginfo.p2);}lv_label_set_text(label, buf);refer_chart_cubic_bezier();
}static void page_obj_init(lv_obj_t * par)
{ginfo.anim_obj = lv_obj_create(par);lv_obj_set_size(ginfo.anim_obj, 30, 30);lv_obj_set_align(ginfo.anim_obj, LV_ALIGN_TOP_LEFT);lv_obj_clear_flag(ginfo.anim_obj, LV_OBJ_FLAG_SCROLLABLE);lv_obj_set_style_bg_color(ginfo.anim_obj, lv_palette_main(LV_PALETTE_RED), LV_PART_MAIN);lv_obj_set_grid_cell(ginfo.anim_obj, LV_GRID_ALIGN_START, 0, 1,LV_GRID_ALIGN_START, 0, 1);ginfo.p1_label = lv_label_create(par);ginfo.p2_label = lv_label_create(par);lv_label_set_text(ginfo.p1_label, "p1:0");lv_label_set_text(ginfo.p2_label, "p2:0");lv_obj_set_grid_cell(ginfo.p1_label, LV_GRID_ALIGN_START, 0, 1,LV_GRID_ALIGN_START, 1, 1);lv_obj_set_grid_cell(ginfo.p2_label, LV_GRID_ALIGN_START, 0, 1,LV_GRID_ALIGN_START, 2, 1);ginfo.p1_slider = lv_slider_create(par);ginfo.p2_slider = lv_slider_create(par);lv_slider_set_range(ginfo.p1_slider, 0, 1024);lv_slider_set_range(ginfo.p2_slider, 0, 1024);lv_obj_set_style_pad_all(ginfo.p1_slider, 2, LV_PART_KNOB);lv_obj_set_style_pad_all(ginfo.p2_slider, 2, LV_PART_KNOB);lv_obj_add_event_cb(ginfo.p1_slider, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);lv_obj_add_event_cb(ginfo.p2_slider, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);lv_obj_set_grid_cell(ginfo.p1_slider, LV_GRID_ALIGN_STRETCH, 1, 1,LV_GRID_ALIGN_START, 1, 1);lv_obj_set_grid_cell(ginfo.p2_slider, LV_GRID_ALIGN_STRETCH, 1, 1,LV_GRID_ALIGN_START, 2, 1);ginfo.run_btn = lv_btn_create(par);lv_obj_add_event_cb(ginfo.run_btn, run_btn_event_handler, LV_EVENT_CLICKED, NULL);lv_obj_t * btn_label = lv_label_create(ginfo.run_btn);lv_label_set_text(btn_label, LV_SYMBOL_PLAY);lv_obj_center(btn_label);lv_obj_set_grid_cell(ginfo.run_btn, LV_GRID_ALIGN_STRETCH, 2, 1,LV_GRID_ALIGN_STRETCH, 1, 2);ginfo.chart = lv_chart_create(par);lv_obj_set_style_pad_all(ginfo.chart, 0, LV_PART_MAIN);lv_obj_set_style_size(ginfo.chart, 0, LV_PART_INDICATOR);lv_chart_set_type(ginfo.chart, LV_CHART_TYPE_SCATTER);ginfo.ser1 = lv_chart_add_series(ginfo.chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y);lv_chart_set_range(ginfo.chart, LV_CHART_AXIS_PRIMARY_Y, 0, 1024);lv_chart_set_range(ginfo.chart, LV_CHART_AXIS_PRIMARY_X, 0, 1024);lv_chart_set_point_count(ginfo.chart, CHART_POINTS_NUM);lv_obj_set_grid_cell(ginfo.chart, LV_GRID_ALIGN_STRETCH, 0, 3,LV_GRID_ALIGN_STRETCH, 3, 1);
}
觉得有帮助的话,打赏一下呗。。
需要商务合作(定制程序)的欢迎私信!!