lvgl 动画设计

发布于:2025-04-23 ⋅ 阅读:(93) ⋅ 点赞:(0)

一、重要接口

  • 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):设置动画的重复次数。若cntLV_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_cbNULL,则删除该变量的所有动画。
  • void lv_anim_del_all(void):删除所有动画。
  • lv_anim_t * lv_anim_get(void * var, lv_anim_exec_xcb_t exec_cb):获取一个变量的指定动画执行函数的动画。若exec_cbNULL,则返回第一个匹配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 256

struct {
    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);
}

觉得有帮助的话,打赏一下呗。。

           

需要商务合作(定制程序)的欢迎私信!! 


网站公告

今日签到

点亮在社区的每一天
去签到