#include "../../lv_examples.h" #if LV_USE_ARC && LV_BUILD_EXAMPLES #define CHART_SIZE 150 #define SLICE_OFFSET 20 typedef struct { int start_angle; int end_angle; int mid_angle; lv_point_t home; bool out; } slice_info_t; typedef struct { lv_obj_t * obj; int start_x; int start_y; int end_x; int end_y; } slice_anim_data_t; static float angle_accum = 0.0f; static slice_info_t * active_info = NULL; static lv_obj_t * active_arc = NULL; static void anim_move_cb(void * var, int32_t v) { slice_anim_data_t * d = (slice_anim_data_t *) var; int32_t x = d->start_x + ((d->end_x - d->start_x) * v) / 100; int32_t y = d->start_y + ((d->end_y - d->start_y) * v) / 100; lv_obj_set_pos(d->obj, x, y); } static void anim_cleanup_cb(lv_anim_t * a) { lv_free(a->var); } static void arc_click_cb(lv_event_t * e) { lv_obj_t * arc = lv_event_get_target_obj(e); slice_info_t * info = (slice_info_t *)lv_event_get_user_data(e); int32_t x_off = (SLICE_OFFSET * lv_trigo_cos(info->mid_angle)) >> LV_TRIGO_SHIFT; int32_t y_off = (SLICE_OFFSET * lv_trigo_sin(info->mid_angle)) >> LV_TRIGO_SHIFT; if(active_info && active_info != info && active_info->out) { slice_anim_data_t * anim_back = (slice_anim_data_t *) lv_malloc(sizeof(slice_anim_data_t)); anim_back->obj = active_arc; anim_back->start_x = lv_obj_get_x(active_arc) - SLICE_OFFSET; anim_back->start_y = lv_obj_get_y(active_arc) - SLICE_OFFSET; anim_back->end_x = active_info->home.x; anim_back->end_y = active_info->home.y; active_info->out = false; lv_anim_t a; lv_anim_init(&a); lv_anim_set_var(&a, anim_back); lv_anim_set_exec_cb(&a, anim_move_cb); lv_anim_set_time(&a, 200); lv_anim_set_values(&a, 0, 100); lv_anim_set_deleted_cb(&a, anim_cleanup_cb); lv_anim_start(&a); } int target_x, target_y; if(info->out) { target_x = info->home.x; target_y = info->home.y; info->out = false; active_info = NULL; active_arc = NULL; } else { target_x = info->home.x + x_off; target_y = info->home.y + y_off; info->out = true; active_info = info; active_arc = arc; } slice_anim_data_t * anim_data = (slice_anim_data_t *) lv_malloc(sizeof(slice_anim_data_t)); anim_data->obj = arc; anim_data->start_x = lv_obj_get_x(arc) - SLICE_OFFSET; anim_data->start_y = lv_obj_get_y(arc) - SLICE_OFFSET; anim_data->end_x = target_x; anim_data->end_y = target_y; lv_anim_t a; lv_anim_init(&a); lv_anim_set_var(&a, anim_data); lv_anim_set_exec_cb(&a, anim_move_cb); lv_anim_set_time(&a, 200); lv_anim_set_values(&a, 0, 100); lv_anim_set_deleted_cb(&a, anim_cleanup_cb); lv_anim_start(&a); } static void create_slice(lv_obj_t * parent, int percentage, lv_color_t color) { if(percentage <= 0) return; float slice_angle = (percentage * 360.0f) / 100.0f; int start = (int)(angle_accum + 0.5f); angle_accum += slice_angle; int end = (int)(angle_accum + 0.5f); if(end > 360) end = 360; lv_obj_t * arc = lv_arc_create(parent); lv_obj_set_size(arc, CHART_SIZE, CHART_SIZE); lv_obj_center(arc); lv_arc_set_mode(arc, LV_ARC_MODE_NORMAL); lv_arc_set_bg_start_angle(arc, start); lv_arc_set_bg_end_angle(arc, end); lv_obj_set_style_arc_width(arc, CHART_SIZE / 2, LV_PART_MAIN); lv_obj_set_style_arc_width(arc, 0, LV_PART_INDICATOR); lv_obj_set_style_arc_color(arc, color, LV_PART_MAIN); lv_obj_set_style_arc_rounded(arc, false, LV_PART_MAIN); lv_obj_remove_style(arc, NULL, LV_PART_KNOB); lv_obj_add_flag(arc, LV_OBJ_FLAG_ADV_HITTEST); lv_obj_t * label = lv_label_create(arc); lv_label_set_text_fmt(label, "%d%%", percentage); int mid_angle = start + ((end - start) / 2); int radius = CHART_SIZE / 4; int x_offset = (radius * lv_trigo_cos(mid_angle)) >> LV_TRIGO_SHIFT; int y_offset = (radius * lv_trigo_sin(mid_angle)) >> LV_TRIGO_SHIFT; lv_obj_align(label, LV_ALIGN_CENTER, x_offset, y_offset); slice_info_t * info = (slice_info_t *) lv_malloc(sizeof(slice_info_t)); info->start_angle = start; info->end_angle = end; info->mid_angle = mid_angle; info->out = false; info->home.x = lv_obj_get_x(arc); info->home.y = lv_obj_get_y(arc); lv_obj_add_event_cb(arc, arc_click_cb, LV_EVENT_CLICKED, info); } void lv_example_arc_3(void) { /* Root container: flex row */ lv_obj_t * root = lv_obj_create(lv_screen_active()); lv_obj_set_size(root, LV_SIZE_CONTENT, LV_SIZE_CONTENT); lv_obj_center(root); lv_obj_set_flex_flow(root, LV_FLEX_FLOW_ROW); lv_obj_set_flex_align(root, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); lv_obj_set_style_pad_all(root, 0, LV_PART_MAIN); lv_obj_set_style_border_width(root, 0, LV_PART_MAIN); lv_obj_set_style_border_color(root, lv_palette_main(LV_PALETTE_RED), LV_PART_MAIN); lv_obj_set_style_bg_opa(root, LV_OPA_TRANSP, LV_PART_MAIN); lv_obj_remove_flag(root, LV_OBJ_FLAG_SCROLLABLE); /* Slices container */ lv_obj_t * slices_container = lv_obj_create(root); lv_obj_set_size(slices_container, CHART_SIZE + 2 * SLICE_OFFSET, CHART_SIZE + 2 * SLICE_OFFSET); lv_obj_set_style_pad_all(slices_container, 0, LV_PART_MAIN); lv_obj_set_style_margin_all(slices_container, 0, LV_PART_MAIN); lv_obj_set_style_border_width(slices_container, 0, LV_PART_MAIN); lv_obj_set_style_border_color(slices_container, lv_palette_main(LV_PALETTE_BLUE), LV_PART_MAIN); lv_obj_set_style_bg_opa(slices_container, LV_OPA_TRANSP, LV_PART_MAIN); lv_obj_remove_flag(slices_container, LV_OBJ_FLAG_SCROLLABLE); /* Create slices */ angle_accum = 0.0f; create_slice(slices_container, 12, lv_palette_main(LV_PALETTE_RED)); create_slice(slices_container, 18, lv_palette_main(LV_PALETTE_BLUE)); create_slice(slices_container, 26, lv_palette_main(LV_PALETTE_GREEN)); create_slice(slices_container, 24, lv_palette_main(LV_PALETTE_ORANGE)); create_slice(slices_container, 20, lv_palette_main(LV_PALETTE_BLUE_GREY)); } #endif