【LVGL笔记】-- 贝塞尔曲线绘制

什么是贝塞尔曲线

贝塞尔曲线(Bézier Curve,也被称为贝塞尔多项式(Bézier Polynomial),是由一系列控制点(Control Point)所定义的一条平滑曲线。Pierre Bézier于1960年开始利用该曲线设计雷诺的车身线条,故命名为贝塞尔曲线。目前,贝塞尔曲线被广泛应用于图形设计、路径优化(无人机、无人驾驶相关)等诸多相关领域中。

贝塞尔具体描述,可以搜索,网上也是一大把,如下链接为推导过程

贝塞尔曲线(Bezier Curve)原理、公式推导及matlab代码实现_beijing_txr的博客-CSDN博客_贝塞尔曲线

lvgl 贝塞尔函数(三阶函数):

lvgl提供了三阶贝塞尔函数(即四个点绘制图形)

/**
 * Calculate a value of a Cubic Bezier function.
 * @param t time in range of [0..LV_BEZIER_VAL_MAX]
 * @param u0 start values in range of [0..LV_BEZIER_VAL_MAX]
 * @param u1 control value 1 values in range of [0..LV_BEZIER_VAL_MAX]
 * @param u2 control value 2 in range of [0..LV_BEZIER_VAL_MAX]
 * @param u3 end values in range of [0..LV_BEZIER_VAL_MAX]
 * @return the value calculated from the given parameters in range of [0..LV_BEZIER_VAL_MAX]
 */

#define LV_BEZIER_VAL_MAX 1024 /**< Max time in Bezier functions (not [0..1] to use integers)*/
#define LV_BEZIER_VAL_SHIFT 10 /**< log2(LV_BEZIER_VAL_MAX): used to normalize up scaled values*/

uint32_t lv_bezier3(uint32_t t, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3)
{
    uint32_t t_rem  = LV_BEZIER_VAL_MAX - t;
    uint32_t t_rem2 = (t_rem * t_rem) >> 10;
    uint32_t t_rem3 = (t_rem2 * t_rem) >> 10;
    uint32_t t2     = (t * t) >> 10;
    uint32_t t3     = (t2 * t) >> 10;

    uint32_t v1 = (t_rem3 * u0) >> 10;
    uint32_t v2 = (3 * t_rem2 * t * u1) >> 20;
    uint32_t v3 = (3 * t_rem * t2 * u2) >> 20;
    uint32_t v4 = (t3 * u3) >> 10;

    return v1 + v2 + v3 + v4;
}

注:LV_BEZIER_VAL_MAX 参数值为什么定义是:2^n,这里是为了在嵌入式中可以通过移位,优化算法(毕竟做除法运算量是相当大的),另外很多时候分两次移位,因为uint32_t 做乘法的时候精度丢失。

t:(0~LV_BEZIER_VAL_MAX) 可以理解为横坐标

u0,u1,u2,u3 四个点纵坐标

v1 + v2 + v3 + v4: 算出当前绘制点的纵坐标

三阶绘制效果

【LVGL笔记】-- 贝塞尔曲线绘制_第1张图片

贝塞尔函数(二阶函数):

自己手搓优化的二阶贝塞尔函数
【LVGL笔记】-- 贝塞尔曲线绘制_第2张图片

转成C语言优化过后如下:

#define MAX_TIME   (256)

uint32_t lv_bezier2(uint32_t t, uint32_t u0, uint32_t u1, uint32_t u2)
{
    uint32_t t_rem  = MAX_TIME - t;
    uint32_t t_rem2 = (t_rem * t_rem) >> 8;
    uint32_t t2 = (t * t) >> 8;

    uint32_t v0 = (t_rem2 * u0) >> 8;
    uint32_t v1 = (2 * u1 * t * t_rem) >> 16;
    uint32_t v2 = (t2 * u2) >> 8;

    return (v0 + v1 + v2);
}
二阶绘制效果

【LVGL笔记】-- 贝塞尔曲线绘制_第3张图片

贝塞尔函数(四阶函数):

根据多项式公式,四阶数学函数和C语言代码如下:

P = (1-t)^4P0 + 4(1-t)^3tP1 + 6(1-t)2*t2P2 + 4(1-t)t^3P3 + t^4*P4

uint32_t lv_bezier4(uint32_t t, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3, uint32_t u4)
{
    //注意数据溢出问题,提前做好移位偏移

    uint32_t t_rem  = MAX_TIME - t;  //差值

    //n次方计算
    uint32_t t_rem2 = (t_rem * t_rem) >> 8;
    uint32_t t_rem3 = (t_rem2 * t_rem) >> 8;   
    uint32_t t_rem4 = (t_rem3 * t_rem) >> 8;  

    //n次方计算
    uint32_t t2 = (t * t) >> 8;  
    uint32_t t3 = (t2 * t) >> 8; 
    uint32_t t4 = (t2 * t2) >> 8;    

    uint32_t v0 = (t_rem4 * u0) >> 8;
    uint32_t v1 = (4 * t_rem3 * t * u1) >> 16;
    uint32_t v2 = (6 * t2 * t_rem2 * u2) >> 16;
    uint32_t v3 = (4 * t_rem * t3 * u3) >> 16;
    uint32_t v4 = (t4 * u4) >> 8;

    return (v0 + v1 + v2 + v3 + v4);
}
四阶绘制效果

多阶用移位方式优化导致了部分精度丢失,所以线段毛刺严重(运算能力强的控制单元可以考虑适用浮点运算)

【LVGL笔记】-- 贝塞尔曲线绘制_第4张图片

绘制代码如下
/**************************************************START OF FILE*****************************************************/






/*------------------------------------------------------------------------------------------------------------------
Includes
*/
#include "lvgl.h"
#include "xGUI_Common.h"
#include "xGUI_ImgLoad.h"
#include "xGUI_Page_Eq.h"

/*------------------------------------------------------------------------------------------------------------------
Macros
*/
#define CHART_POINTS_NUM 256
#define MAX_TIME      (256)
#define USE_BEZIER_4  (1)   //四阶还是二阶

typedef struct
{
    bool is_style_init;

    //style list
    lv_style_t style_btn_main;

    lv_style_t style_src_main;
    lv_style_t style_src_main_focused;  
    lv_style_t style_src_main_enited;       
    lv_style_t style_src_indicator;

    lv_style_t style_combox_main;

    lv_obj_t *pWidgetBtnClose;
    lv_obj_t *pWidgetBtnSave;
    lv_obj_t *pWidgetCombox[3];
    lv_obj_t *pWidgetChart[2];

    lv_obj_t *pWidgetSubChart;
    lv_obj_t *pWidgetBtnChart[3];

    lv_chart_series_t *ser1[2];

    lv_obj_t *pWidgetArc[6];
    uint16_t arcPara[6];
}ui_eq_page_manage_t;

/*------------------------------------------------------------------------------------------------------------------
Variables
*/
extern lv_obj_t *pMainWidget;
ui_eq_page_manage_t ui_eq_page_manage = 
{
    .arcPara[0] = 127,
    .arcPara[1] = 127,
    .arcPara[2] = 127,
    .arcPara[3] = 127,
    .arcPara[4] = 127,
    .arcPara[5] = 127,
};


/*------------------------------------------------------------------------------------------------------------------
Functions
*/
static void eq_style_init(void);
static void refer_chart_cubic_bezier(void);

static void btn_event_callback(lv_event_t * e)
{
    lv_obj_t *obj = lv_event_get_target(e);    
    lv_event_code_t event = lv_event_get_code(e);

    if (event == LV_EVENT_CLICKED)
    {
		if(obj == ui_eq_page_manage.pWidgetBtnClose)
		{
			DisplayPara.MenuID = UI_PAGE_CHAIN;
		}
		else if(obj == ui_eq_page_manage.pWidgetBtnSave)
		{
			
		}        
    }
}

static void arc_event_callback(lv_event_t * e)
{
	lv_obj_t *obj = lv_event_get_target(e);
	lv_event_code_t event = lv_event_get_code(e);
    uint16_t* puser_data = (uint16_t*)lv_event_get_user_data(e);
    char buf[6];

    int16_t subData;

	if (event == LV_EVENT_VALUE_CHANGED)
	{
		*puser_data = lv_arc_get_value(obj);

        lv_obj_t *label = lv_obj_get_child(obj, NULL);

        lv_snprintf(buf, sizeof(buf), "%d", *puser_data);
        lv_label_set_text(label ,buf);
	}

    refer_chart_cubic_bezier();   
}

/*
********************************************************************************************************************
@ Brief  : 贝塞尔二阶函数

@ Param  : None

@ Return : None

@ Author : lyc

@  Date  : 2023 - 02 - 17
********************************************************************************************************************
*/
uint32_t lv_bezier2(uint32_t t, uint32_t u0, uint32_t u1, uint32_t u2)
{
    uint32_t t_rem  = MAX_TIME - t;
    uint32_t t_rem2 = (t_rem * t_rem) >> 8;
    uint32_t t2 = (t * t) >> 8;

    uint32_t v0 = (t_rem2 * u0) >> 8;
    uint32_t v1 = (2 * u1 * t * t_rem) >> 16;
    uint32_t v2 = (t2 * u2) >> 8;

    return (v0 + v1 + v2);
}

uint32_t lv_bezier4(uint32_t t, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3, uint32_t u4)
{
    //注意数据溢出问题,提前做好移位偏移

    uint32_t t_rem  = MAX_TIME - t;  //差值

    //n次方计算
    uint32_t t_rem2 = (t_rem * t_rem) >> 8;
    uint32_t t_rem3 = (t_rem2 * t_rem) >> 8;   
    uint32_t t_rem4 = (t_rem3 * t_rem) >> 8;  

    //n次方计算
    uint32_t t2 = (t * t) >> 8;  
    uint32_t t3 = (t2 * t) >> 8; 
    uint32_t t4 = (t2 * t2) >> 8;    

    uint32_t v0 = (t_rem4 * u0) >> 8;
    uint32_t v1 = (4 * t_rem3 * t * u1) >> 16;
    uint32_t v2 = (6 * t2 * t_rem2 * u2) >> 16;
    uint32_t v3 = (4 * t_rem * t3 * u3) >> 16;
    uint32_t v4 = (t4 * u4) >> 8;

    return (v0 + v1 + v2 + v3 + v4);
}

/*
********************************************************************************************************************
@ Brief  : 界面显示初始化

@ Param  : None

@ Return : None

@ Author : lyc

@  Date  : 2023 - 01 - 29
********************************************************************************************************************
*/
void gui_eq_init(void)
{
    int i;
    lv_obj_t *label;
    char buf[30];

    eq_style_init();

    ui_eq_page_manage.pWidgetBtnClose = lv_label_create(pMainWidget);
    lv_obj_align(ui_eq_page_manage.pWidgetBtnClose, LV_ALIGN_DEFAULT, 740, 10);
    lv_obj_set_style_text_font(ui_eq_page_manage.pWidgetBtnClose, &icon_font_32, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(ui_eq_page_manage.pWidgetBtnClose, lv_color_white(), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_label_set_text(ui_eq_page_manage.pWidgetBtnClose, LV_SYMBOL_CLOSE);
    lv_obj_add_flag(ui_eq_page_manage.pWidgetBtnClose, LV_OBJ_FLAG_CLICKABLE);
    lv_obj_add_event_cb(ui_eq_page_manage.pWidgetBtnClose, btn_event_callback, LV_EVENT_CLICKED, NULL);        
    
    label = lv_label_create(pMainWidget);
    lv_obj_align(label, LV_ALIGN_DEFAULT, 50, 5);
    lv_obj_set_style_text_color(label, lv_palette_main(LV_PALETTE_PURPLE), LV_PART_MAIN | LV_STATE_DEFAULT);  //
    lv_obj_set_style_text_font(label, &bold_font_20, LV_PART_MAIN);
    lv_label_set_text(label , "AI EQ MASTER");

    ui_eq_page_manage.pWidgetCombox[0] = lv_dropdown_create(pMainWidget);
    lv_obj_set_size(ui_eq_page_manage.pWidgetCombox[0], 200, 40);
    lv_obj_align(ui_eq_page_manage.pWidgetCombox[0], LV_ALIGN_DEFAULT, 50, 35);
    lv_obj_add_style(ui_eq_page_manage.pWidgetCombox[0],&ui_eq_page_manage.style_combox_main,LV_PART_MAIN);
	lv_dropdown_clear_options(ui_eq_page_manage.pWidgetCombox[0]);
    for (i = 0; i < 10; i++)
    {
    	lv_snprintf(buf,sizeof(buf), "Type: Destortion%02d", i);
		lv_dropdown_add_option(ui_eq_page_manage.pWidgetCombox[0], buf, i);
    }
    lv_dropdown_set_symbol(ui_eq_page_manage.pWidgetCombox[0], LV_SYMBOL_DOWN);

    ui_eq_page_manage.pWidgetCombox[1] = lv_dropdown_create(pMainWidget);
    lv_obj_set_size(ui_eq_page_manage.pWidgetCombox[1], 250, 40);
    lv_obj_align(ui_eq_page_manage.pWidgetCombox[1], LV_ALIGN_DEFAULT, 270, 35);
    lv_obj_add_style(ui_eq_page_manage.pWidgetCombox[1],&ui_eq_page_manage.style_combox_main,LV_PART_MAIN);
	lv_dropdown_clear_options(ui_eq_page_manage.pWidgetCombox[1]);
    for (i = 0; i < 10; i++)
    {
    	lv_snprintf(buf,sizeof(buf), "80`s Rock Phythm %02d", i);
		lv_dropdown_add_option(ui_eq_page_manage.pWidgetCombox[1], buf, i);
    }
    lv_dropdown_set_symbol(ui_eq_page_manage.pWidgetCombox[1], LV_SYMBOL_DOWN);
	
    ui_eq_page_manage.pWidgetCombox[2] = lv_dropdown_create(pMainWidget);
    lv_obj_set_size(ui_eq_page_manage.pWidgetCombox[2], 100, 40);
    lv_obj_align(ui_eq_page_manage.pWidgetCombox[2], LV_ALIGN_DEFAULT, 620, 35);
    lv_obj_add_style(ui_eq_page_manage.pWidgetCombox[2],&ui_eq_page_manage.style_combox_main,LV_PART_MAIN);
	lv_dropdown_clear_options(ui_eq_page_manage.pWidgetCombox[2]);
    for (i = 0; i < 10; i++)
    {
    lv_snprintf(buf,sizeof(buf), "Slot%02d", i);
        lv_dropdown_add_option(ui_eq_page_manage.pWidgetCombox[2], buf, i);
    }
    lv_dropdown_set_symbol(ui_eq_page_manage.pWidgetCombox[2], LV_SYMBOL_DOWN);

    ui_eq_page_manage.pWidgetBtnSave = lv_label_create(pMainWidget);
    lv_obj_align(ui_eq_page_manage.pWidgetBtnSave, LV_ALIGN_DEFAULT, 560, 40);
    lv_obj_set_style_text_font(ui_eq_page_manage.pWidgetBtnSave, &icon_font_32, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(ui_eq_page_manage.pWidgetBtnSave, lv_color_white(), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_label_set_text(ui_eq_page_manage.pWidgetBtnSave, LV_SYMBOL_SAVE);
    lv_obj_add_flag(ui_eq_page_manage.pWidgetBtnSave, LV_OBJ_FLAG_CLICKABLE);
    lv_obj_add_event_cb(ui_eq_page_manage.pWidgetBtnSave, btn_event_callback, LV_EVENT_CLICKED, NULL);    

#if USE_BEZIER_4
    ui_eq_page_manage.pWidgetChart[0] = lv_chart_create(pMainWidget);
    lv_obj_align(ui_eq_page_manage.pWidgetChart[0],LV_ALIGN_DEFAULT,50,90);
    lv_obj_set_size(ui_eq_page_manage.pWidgetChart[0], 700, 260);
    lv_obj_set_style_line_color(ui_eq_page_manage.pWidgetChart[0], lv_palette_main(LV_PALETTE_GREY), LV_PART_MAIN);
    lv_obj_set_style_line_opa(ui_eq_page_manage.pWidgetChart[0], LV_OPA_80, LV_PART_MAIN);
    lv_obj_set_style_pad_all(ui_eq_page_manage.pWidgetChart[0], 0, LV_PART_MAIN);
    lv_obj_set_style_size(ui_eq_page_manage.pWidgetChart[0], 0, LV_PART_INDICATOR);
    lv_obj_set_style_bg_color(ui_eq_page_manage.pWidgetChart[0],lv_color_black(),LV_PART_MAIN);  
    lv_obj_set_style_border_width(ui_eq_page_manage.pWidgetChart[0], 0, LV_PART_MAIN);
    lv_chart_set_type(ui_eq_page_manage.pWidgetChart[0], LV_CHART_TYPE_SCATTER);
    lv_chart_set_div_line_count(ui_eq_page_manage.pWidgetChart[0], 11, 7);
    ui_eq_page_manage.ser1[0] = lv_chart_add_series(ui_eq_page_manage.pWidgetChart[0], lv_palette_main(LV_PALETTE_AMBER), LV_CHART_AXIS_PRIMARY_Y);
    lv_chart_set_range(ui_eq_page_manage.pWidgetChart[0], LV_CHART_AXIS_PRIMARY_Y, 0, CHART_POINTS_NUM);
    lv_chart_set_range(ui_eq_page_manage.pWidgetChart[0], LV_CHART_AXIS_PRIMARY_X, 0, CHART_POINTS_NUM);
    lv_chart_set_point_count(ui_eq_page_manage.pWidgetChart[0], CHART_POINTS_NUM);
#else
    for(i=0;i<2;i++)
    {
        ui_eq_page_manage.pWidgetChart[i] = lv_chart_create(pMainWidget);
        lv_obj_align(ui_eq_page_manage.pWidgetChart[i],LV_ALIGN_DEFAULT,50+350*i,90);
        lv_obj_set_size(ui_eq_page_manage.pWidgetChart[i], 350, 260);
        lv_obj_set_style_line_color(ui_eq_page_manage.pWidgetChart[i], lv_palette_main(LV_PALETTE_GREY), LV_PART_MAIN);
        lv_obj_set_style_line_opa(ui_eq_page_manage.pWidgetChart[i], LV_OPA_80, LV_PART_MAIN);
        lv_obj_set_style_pad_all(ui_eq_page_manage.pWidgetChart[i], 0, LV_PART_MAIN);
        lv_obj_set_style_size(ui_eq_page_manage.pWidgetChart[i], 0, LV_PART_INDICATOR);
        lv_obj_set_style_bg_color(ui_eq_page_manage.pWidgetChart[i],lv_color_black(),LV_PART_MAIN);  
        lv_obj_set_style_border_width(ui_eq_page_manage.pWidgetChart[i], 0, LV_PART_MAIN);
        lv_chart_set_type(ui_eq_page_manage.pWidgetChart[i], LV_CHART_TYPE_SCATTER);
        lv_chart_set_div_line_count(ui_eq_page_manage.pWidgetChart[i], 11, 7);
        ui_eq_page_manage.ser1[i] = lv_chart_add_series(ui_eq_page_manage.pWidgetChart[i], lv_palette_main(LV_PALETTE_AMBER), LV_CHART_AXIS_PRIMARY_Y);
        lv_chart_set_range(ui_eq_page_manage.pWidgetChart[i], LV_CHART_AXIS_PRIMARY_Y, 0, CHART_POINTS_NUM);
        lv_chart_set_range(ui_eq_page_manage.pWidgetChart[i], LV_CHART_AXIS_PRIMARY_X, 0, CHART_POINTS_NUM);
        lv_chart_set_point_count(ui_eq_page_manage.pWidgetChart[i], CHART_POINTS_NUM);
    }
#endif    
    ui_eq_page_manage.pWidgetSubChart = lv_obj_create(pMainWidget);
    lv_obj_set_size(ui_eq_page_manage.pWidgetSubChart, 280, 60);
    lv_obj_align(ui_eq_page_manage.pWidgetSubChart,LV_ALIGN_TOP_MID,0,270);
    lv_obj_set_style_border_opa(ui_eq_page_manage.pWidgetSubChart,LV_OPA_TRANSP,LV_PART_MAIN);
    lv_obj_set_style_bg_color(ui_eq_page_manage.pWidgetSubChart,lv_palette_main(LV_PALETTE_GREY),LV_PART_MAIN);
    lv_obj_set_style_bg_opa(ui_eq_page_manage.pWidgetSubChart,LV_OPA_40,LV_PART_MAIN);
    lv_obj_set_style_pad_gap(ui_eq_page_manage.pWidgetSubChart,0,LV_PART_MAIN);
    lv_obj_clear_flag(ui_eq_page_manage.pWidgetSubChart, LV_OBJ_FLAG_SCROLLABLE);

    ui_eq_page_manage.pWidgetBtnChart[0] = lv_btn_create(ui_eq_page_manage.pWidgetSubChart);
    lv_obj_set_size(ui_eq_page_manage.pWidgetBtnChart[0], 40, 40);
    lv_obj_align(ui_eq_page_manage.pWidgetBtnChart[0], LV_ALIGN_CENTER, -90, 0);
    lv_obj_add_style(ui_eq_page_manage.pWidgetBtnChart[0],&ui_eq_page_manage.style_btn_main,LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_add_event_cb(ui_eq_page_manage.pWidgetBtnChart[0], btn_event_callback, LV_EVENT_CLICKED, NULL); 
    label = lv_label_create(ui_eq_page_manage.pWidgetBtnChart[0]);
    lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
    lv_obj_set_style_text_font(label, &icon_font_32, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_label_set_text(label, "\uF111");

    ui_eq_page_manage.pWidgetBtnChart[1] = lv_btn_create(ui_eq_page_manage.pWidgetSubChart);
    lv_obj_set_size(ui_eq_page_manage.pWidgetBtnChart[1], 40, 40);
    lv_obj_align(ui_eq_page_manage.pWidgetBtnChart[1], LV_ALIGN_CENTER, 0, 0);
    lv_obj_add_style(ui_eq_page_manage.pWidgetBtnChart[1],&ui_eq_page_manage.style_btn_main,LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_add_event_cb(ui_eq_page_manage.pWidgetBtnChart[1], btn_event_callback, LV_EVENT_CLICKED, NULL); 
    label = lv_label_create(ui_eq_page_manage.pWidgetBtnChart[1]);
    lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
    lv_obj_set_style_text_font(label, &icon_font_32, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_label_set_text(label, "\uF011");

    ui_eq_page_manage.pWidgetBtnChart[2] = lv_btn_create(ui_eq_page_manage.pWidgetSubChart);
    lv_obj_set_size(ui_eq_page_manage.pWidgetBtnChart[2], 40, 40);
    lv_obj_align(ui_eq_page_manage.pWidgetBtnChart[2], LV_ALIGN_CENTER, 90, 0);
    lv_obj_add_style(ui_eq_page_manage.pWidgetBtnChart[2],&ui_eq_page_manage.style_btn_main,LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_add_event_cb(ui_eq_page_manage.pWidgetBtnChart[2], btn_event_callback, LV_EVENT_CLICKED, NULL); 
    label = lv_label_create(ui_eq_page_manage.pWidgetBtnChart[2]);
    lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
    lv_obj_set_style_text_font(label, &icon_font_32, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_label_set_text(label, "\uF014");

    for(i=0;i<6;i++)
    {
        ui_eq_page_manage.pWidgetArc[i] = lv_arc_create(pMainWidget);
        lv_obj_set_size(ui_eq_page_manage.pWidgetArc[i], 80, 80);
        lv_obj_align(ui_eq_page_manage.pWidgetArc[i],LV_ALIGN_TOP_MID, -300 + 120*i, 370);
        lv_arc_set_bg_angles(ui_eq_page_manage.pWidgetArc[i],135,45);
        lv_arc_set_range(ui_eq_page_manage.pWidgetArc[i], 0, MAX_TIME);
        lv_arc_set_value(ui_eq_page_manage.pWidgetArc[i], ui_eq_page_manage.arcPara[i]);
        lv_obj_add_style(ui_eq_page_manage.pWidgetArc[i],&ui_eq_page_manage.style_src_main,LV_PART_MAIN);
        lv_obj_add_style(ui_eq_page_manage.pWidgetArc[i],&ui_eq_page_manage.style_src_indicator,LV_PART_INDICATOR);
        lv_obj_add_style(ui_eq_page_manage.pWidgetArc[i],&ui_eq_page_manage.style_src_main_focused,LV_PART_MAIN | LV_STATE_FOCUSED);  
        lv_obj_add_style(ui_eq_page_manage.pWidgetArc[i],&ui_eq_page_manage.style_src_main_enited,LV_PART_MAIN | LV_STATE_EDITED);      
        lv_obj_remove_style(ui_eq_page_manage.pWidgetArc[i], NULL, LV_PART_KNOB);
        lv_group_add_obj(pGroupEncoder,ui_eq_page_manage.pWidgetArc[i]);

        label = lv_label_create(ui_eq_page_manage.pWidgetArc[i]);
        lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
        lv_obj_set_style_text_color(label, lv_color_white(), LV_PART_MAIN | LV_STATE_DEFAULT);
        lv_snprintf(buf, sizeof(buf), "%d", ui_eq_page_manage.arcPara[i]);
        lv_label_set_text(label ,buf);
        lv_obj_add_event_cb(ui_eq_page_manage.pWidgetArc[i],arc_event_callback,LV_EVENT_VALUE_CHANGED,&ui_eq_page_manage.arcPara[i]);
    }
    lv_group_focus_obj(ui_eq_page_manage.pWidgetArc[0]); 

    lv_obj_set_style_arc_color(ui_eq_page_manage.pWidgetArc[0],lv_palette_lighten(LV_PALETTE_GREEN,1),LV_PART_INDICATOR | LV_STATE_DEFAULT);
    lv_obj_set_style_arc_color(ui_eq_page_manage.pWidgetArc[1],lv_palette_lighten(LV_PALETTE_PINK,1),LV_PART_INDICATOR | LV_STATE_DEFAULT);
    lv_obj_set_style_arc_color(ui_eq_page_manage.pWidgetArc[2],lv_palette_lighten(LV_PALETTE_RED,1),LV_PART_INDICATOR | LV_STATE_DEFAULT);
    lv_obj_set_style_arc_color(ui_eq_page_manage.pWidgetArc[3],lv_palette_lighten(LV_PALETTE_BLUE,1),LV_PART_INDICATOR | LV_STATE_DEFAULT);
    lv_obj_set_style_arc_color(ui_eq_page_manage.pWidgetArc[4],lv_palette_lighten(LV_PALETTE_BLUE,3),LV_PART_INDICATOR | LV_STATE_DEFAULT);
    lv_obj_set_style_arc_color(ui_eq_page_manage.pWidgetArc[5],lv_palette_lighten(LV_PALETTE_PURPLE,1),LV_PART_INDICATOR | LV_STATE_DEFAULT);

    refer_chart_cubic_bezier();
}

/*
********************************************************************************************************************
@ Brief  : 

@ Param  : None

@ Return : None

@  Date  : 2023 - 02 - 02
********************************************************************************************************************
*/
void xGUI_Page_Eq(const DisplayPara_TypeDef *pDisPlay)
{
   
    if(pDisPlay->MenuID != TempDisplayPara.MenuID )
	{
		if(pMainWidget != NULL)lv_obj_clean(pMainWidget);
        gui_eq_init();
		TempDisplayPara.MenuID = pDisPlay->MenuID;
	}    
}


/*
********************************************************************************************************************
@ Brief  : 风格类型初始化:当前界面所有控件的风格整理

@ Param  : None

@ Return : None

@ Author : lyc

@  Date  : 2023 - 01 - 29
********************************************************************************************************************
*/
static void eq_style_init(void)
{
    if(ui_eq_page_manage.is_style_init == false)
    {
        lv_style_init(&ui_eq_page_manage.style_btn_main);
        lv_style_set_radius(&ui_eq_page_manage.style_btn_main,4);
        lv_style_set_bg_color(&ui_eq_page_manage.style_btn_main,lv_palette_main(LV_PALETTE_GREY));
        lv_style_set_bg_opa(&ui_eq_page_manage.style_btn_main,LV_OPA_30);
        lv_style_set_shadow_opa(&ui_eq_page_manage.style_btn_main,LV_OPA_TRANSP);

        lv_style_init(&ui_eq_page_manage.style_src_main);
        lv_style_set_arc_color(&ui_eq_page_manage.style_src_main,lv_palette_darken(LV_PALETTE_GREY,3));
        lv_style_set_arc_width(&ui_eq_page_manage.style_src_main,8);

        lv_style_init(&ui_eq_page_manage.style_src_indicator);
        lv_style_set_arc_color(&ui_eq_page_manage.style_src_indicator,lv_palette_lighten(LV_PALETTE_ORANGE,1));
        lv_style_set_arc_width(&ui_eq_page_manage.style_src_indicator,8);

        lv_style_init(&ui_eq_page_manage.style_src_main_focused);
        lv_style_set_bg_opa(&ui_eq_page_manage.style_src_main_focused,LV_OPA_TRANSP);  
        lv_style_set_border_opa(&ui_eq_page_manage.style_src_main_focused,LV_OPA_COVER);
        lv_style_set_shadow_width(&ui_eq_page_manage.style_src_main_focused,10);
        lv_style_set_shadow_color(&ui_eq_page_manage.style_src_main_focused,lv_palette_lighten(LV_PALETTE_BLUE,2));
        lv_style_set_arc_color(&ui_eq_page_manage.style_src_main_focused,lv_palette_lighten(LV_PALETTE_GREY,1));

        lv_style_init(&ui_eq_page_manage.style_src_main_enited);
        lv_style_set_bg_opa(&ui_eq_page_manage.style_src_main_enited,LV_OPA_TRANSP);  
        lv_style_set_border_opa(&ui_eq_page_manage.style_src_main_enited,LV_OPA_COVER);
        lv_style_set_shadow_width(&ui_eq_page_manage.style_src_main_enited,10);
        lv_style_set_shadow_color(&ui_eq_page_manage.style_src_main_enited,lv_palette_lighten(LV_PALETTE_PINK,2)); 
        lv_style_set_arc_color(&ui_eq_page_manage.style_src_main_enited,lv_palette_lighten(LV_PALETTE_GREY,3));

        lv_style_init(&ui_eq_page_manage.style_combox_main);
        lv_style_set_radius(&ui_eq_page_manage.style_combox_main,9);
        lv_style_set_border_color(&ui_eq_page_manage.style_combox_main,lv_palette_main(LV_PALETTE_PURPLE));
        lv_style_set_border_width(&ui_eq_page_manage.style_combox_main,2);
        lv_style_set_bg_color(&ui_eq_page_manage.style_combox_main,lv_color_black());
        lv_style_set_text_color(&ui_eq_page_manage.style_combox_main, lv_color_white());
        
        ui_eq_page_manage.is_style_init = true;
    }
}

static void refer_chart_cubic_bezier(void)
{
    int i;
    int32_t step;
#if USE_BEZIER_4
    for(i = 0; i <= CHART_POINTS_NUM; i ++)
    {
        step = lv_bezier4(i, ui_eq_page_manage.arcPara[0], ui_eq_page_manage.arcPara[1], ui_eq_page_manage.arcPara[2],ui_eq_page_manage.arcPara[3], ui_eq_page_manage.arcPara[4]);
        lv_chart_set_value_by_id2(ui_eq_page_manage.pWidgetChart[0], ui_eq_page_manage.ser1[0], i, i, step);
    }

    lv_chart_refresh(ui_eq_page_manage.pWidgetChart[0]);
#else
    for(i = 0; i <= CHART_POINTS_NUM; i ++)
    {
        step = lv_bezier2(i, ui_eq_page_manage.arcPara[0], ui_eq_page_manage.arcPara[1], ui_eq_page_manage.arcPara[2]);
        lv_chart_set_value_by_id2(ui_eq_page_manage.pWidgetChart[0], ui_eq_page_manage.ser1[0], i, i, step);
        step = lv_bezier2(i, ui_eq_page_manage.arcPara[2], ui_eq_page_manage.arcPara[3], ui_eq_page_manage.arcPara[4]);
        lv_chart_set_value_by_id2(ui_eq_page_manage.pWidgetChart[1], ui_eq_page_manage.ser1[1], i, i, step);
    }

    lv_chart_refresh(ui_eq_page_manage.pWidgetChart[0]);
	lv_chart_refresh(ui_eq_page_manage.pWidgetChart[1]);
#endif    
}
/****************************************************END OF FILE*****************************************************/


理解贝塞尔曲线后,可以根据需要搭建多阶算法(阶数越多,曲线拟合更贴切,但算法量越大,对算力较弱的芯片不推荐)

你可能感兴趣的:(lvgl,ui)