目录
图表通过lv_chart_create创建。
lv_obj_t *chart = lv_chart_create(lv_scr_act());
lv_obj_set_size(chart, 240, 240);
lv_obj_align(chart, LV_ALIGN_CENTER, 0, 0);
四个边分别对应主X轴,主Y轴,副X轴,副Y轴。
1. 初始化
1.1 添加数据
lv_chart_series_t * lv_chart_add_series(lv_obj_t * obj, lv_color_t color, lv_chart_axis_t axis);
lv_chart_add_series可以添加一个数列到图表,每调用一次就会增加一个。
color是该数列在图表中显示的颜色。axis是数列在哪个Y轴上,其有效参数有:
LV_CHART_AXIS_PRIMARY_Y = 0x00,
LV_CHART_AXIS_SECONDARY_Y = 0x01,
函数返回该数列的指针。
lv_chart_series_t* ser1 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y);
通过lv_chart_set_next_value向数列添加数据
void lv_chart_set_next_value(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t value);
value的最佳的范围是0-100,即0%-100%占比图表显示。每调用一次这个函数就往数列里面添加一个数据。
lv_chart_set_next_value(chart, ser1, 0);
lv_chart_set_next_value(chart, ser1, 100);
lv_chart_set_next_value(chart, ser1, 200);
可以看到第三个点溢出图表了,这是因为默认的数据范围是0-100。
另外,可以通过数组直接设置一组数据。
void lv_chart_set_ext_y_array(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t array[]);
void lv_chart_set_ext_x_array(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t array[]);
static const lv_coord_t value[] = { 0, 100, 300 };
lv_chart_set_ext_y_array(chart, chartSer1, (lv_coord_t*)value);
不过这种方式最少是一屏数据,上图中就是10个点都更新了,虽然只更新了3个数据。严格来说,这里应该是会数组溢出的,应该要初始化为10个数据量的数组才对。
1.2 设置范围
void lv_chart_set_range(lv_obj_t * obj, lv_chart_axis_t axis, lv_coord_t min, lv_coord_t max);
前面设置数字超过100就会超出图表显示范围,可以通过这个函数设置范围,其中axis表示需要设置哪个轴的范围。
lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, 0, 300);
1.3 设置类型
void lv_chart_set_type(lv_obj_t * obj, lv_chart_type_t type);
type是新的类型,默认是LINE,NONE就是没有显示了。
enum {
LV_CHART_TYPE_NONE, /**< Don't draw the series*/
LV_CHART_TYPE_LINE, /**< Connect the points with lines*/
LV_CHART_TYPE_BAR, /**< Draw columns*/
LV_CHART_TYPE_SCATTER, /**< Draw points and lines in 2D (x,y coordinates)*/
};
其他2种的显示效果如下:
SCATTER的类型(即在二维坐标内绘制点和线)要用到Value2,否则显示就和上面一样,是一条垂直的直线。
void lv_chart_set_next_value2(lv_obj_t * obj, lv_chart_series_t * ser, lv_coord_t x_value, lv_coord_t y_value);
注意,在设置value2前必须设置好Type,否则不会显示出数据。
lv_chart_set_type(chart, LV_CHART_TYPE_SCATTER);
lv_chart_set_next_value2(chart, ser1, 0, 0);
lv_chart_set_next_value2(chart, ser1, 50, 100);
lv_chart_set_next_value2(chart, ser1, 100, 300);
1.4 设置显示刷新方式
void lv_chart_set_update_mode(lv_obj_t * obj, lv_chart_update_mode_t update_mode);
支持2种方式:
enum {
LV_CHART_UPDATE_MODE_SHIFT, /**< Shift old data to the left and add the new one the right*/
LV_CHART_UPDATE_MODE_CIRCULAR, /**< Add the new data in a circular way*/
};
其中LV_CHART_UPDATE_MODE_SHIFT是默认的方式。
在主循环中添加测试代码,循环增加数据
if ((gDly % 1000) == 0)
{
uint16_t x = (gDly / 1000) % 100;
uint16_t y = (gDly / 1000) % 300;
//lv_chart_set_next_value2(chart, chartSer1, x, y);
lv_chart_set_next_value(chart, chartSer1, y);
}
gDly+=100;
注意变量要改为全局变量。
2种方式显示效果如下图:
SHIFT表示每个点都会更新到前一个点,最左侧的点消失。而CIRCULAR是循环添加。
注意,当类型为LV_CHART_TYPE_SCATTER时,这个设置没有效果,都是下面的显示方式。
1.5 设置显示点数
上面的例子中不论添加多少个数据,显示的点数总是10个,可以通过设置修改这个值。
void lv_chart_set_point_count(lv_obj_t * obj, uint16_t cnt);
例如设置为20个点显示
lv_chart_set_point_count(chart, 20);
1.6 设施栅格数
void lv_chart_set_div_line_count(lv_obj_t * obj, uint8_t hdiv, uint8_t vdiv);
hdiv是水平方向的栅格数,vdiv是垂直方向。
lv_chart_set_div_line_count(chart, 5, 10);
1.7 设置记号和标签
void lv_chart_set_axis_tick(lv_obj_t * obj, lv_chart_axis_t axis, lv_coord_t major_len, lv_coord_t minor_len,
lv_coord_t major_cnt, lv_coord_t minor_cnt, bool label_en, lv_coord_t draw_size);
axis:对应轴
major_len:主标记的长度
minor_len:副标记的长度
major_cnt:主标记的个数
minor_cnt:副标记的个数
label_en:是否增加标签显示
draw_size:需要显示标记和标签的大小,像素为单位,20pixel + draw_size是实际显示的长度。
lv_chart_set_axis_tick(chart, LV_CHART_AXIS_PRIMARY_Y, 5, 3, 4, 2, true, 40);
长的标记是Major Tick,短的标记是Minor Tick。Major设置4的cnt,所以图上有4个长的。当lable_en为true时,图上会显示数字。
1.8 设置光标
lv_chart_cursor_t * lv_chart_add_cursor(lv_obj_t * obj, lv_color_t color, lv_dir_t dir);
dir表示哪个方向添加光标,有效参数是:
LV_DIR_RIGHT/LEFT/TOP/BOTTOM/HOR/VER/ALL
可以通过OR设置多个方向。
lv_chart_cursor_t* cursor;
cursor = lv_chart_add_cursor(chart, lv_palette_main(LV_PALETTE_GREEN), LV_DIR_RIGHT);
这个函数只是添加一个光标,还需要通过lv_chart_set_cursor_pos设置光标位置。
void lv_chart_set_cursor_pos(lv_obj_t * chart, lv_chart_cursor_t * cursor, lv_point_t * pos);
pos是光标的位置
lv_point_t point = {50, 120};
lv_chart_set_cursor_pos(chart, cursor, &point);
LV_DIR_RIGHT/LEFT/TOP/BOTTOM/HOR/VER/ALL以此显示效果如下:
1.9 缩放
可以在X或Y方向对图标缩放。
void lv_chart_set_zoom_x(lv_obj_t * obj, uint16_t zoom_x);
void lv_chart_set_zoom_y(lv_obj_t * obj, uint16_t zoom_y);
zoom_x和zoom_y的含义和图片缩放一样,256表示原大小。
lv_chart_set_zoom_x(chart, 512);
2. Parts
LV_PART_MAIN:可以用来修改背景和栅格线的样式。参考3.1
LV_PART_SCROLLBAR:当放大的时候,会绘制ScrollBar。参考3.2
LV_PART_ITEMS:对应series画的线或柱状图。参考3.3
LV_PART_INDICATOR:对应ITEMS上的点。参考3.4
LV_PART_CURSOR:对应光标。参考3.5
LV_PART_TICKS:对应记号和标签。参考3.6
3. 样式
3.1 修改背景色
lv_obj_set_style_bg_color(chart, lv_palette_main(LV_PALETTE_BLUE_GREY), LV_PART_MAIN);
3.2 修改栅格线颜色
lv_obj_set_style_line_color(chart, lv_palette_main(LV_PALETTE_BLUE_GREY), LV_PART_MAIN);
3.3 设置滚动条颜色
lv_obj_set_style_bg_color(chart, lv_palette_main(LV_PALETTE_ORANGE), LV_PART_SCROLLBAR);
3.4 设置ITEMS的线宽
lv_obj_set_style_line_width(chart, 10, LV_PART_ITEMS);
3.5 设置ITEMS点的大小
lv_obj_set_style_width(chart, 10, LV_PART_INDICATOR);
lv_obj_set_style_height(chart, 10, LV_PART_INDICATOR);
3.6 设置光标线宽
lv_obj_set_style_line_width(chart, 10, LV_PART_CURSOR);
3.7 设置记号和标签颜色
lv_obj_set_style_line_color(chart, lv_palette_main(LV_PALETTE_ORANGE), LV_PART_TICKS);
lv_obj_set_style_text_color(chart, lv_palette_main(LV_PALETTE_YELLOW), LV_PART_TICKS);
3.8 更改标签
标签默认是采用数字,可以通过LV_EVENT_DRAW_PART_BEGIN事件重绘标签。
lv_obj_add_event_cb(chart, chart_draw_event_cb, LV_EVENT_DRAW_PART_BEGIN, NULL);
在事件函数chart_draw_event_cb中获取绘制描述符
static void chart_draw_event_cb(lv_event_t* e)
{
lv_obj_draw_part_dsc_t* dsc = lv_event_get_draw_part_dsc(e);
}
然后判断是不是绘制的是不是标记或标签
if (!lv_obj_draw_part_check_type(dsc, &lv_chart_class, LV_CHART_DRAW_PART_TICK_LABEL))
return;
再判断是不是标签
if (dsc->text)
{
}
然后判断是不是对应的轴
if (dsc->id == LV_CHART_AXIS_PRIMARY_Y)
{
}
最后更新字符串显示
const char* level[] = { "L1", "L2", "L3", "L4"};
lv_snprintf(dsc->text, dsc->text_length, "%s", level[dsc->value / 100]);
这里dsc->value的值是Y轴的值,因为之前设置的值会显示0, 100, 200, 300,所以这里要除以100。