diff --git a/demos/widgets/lv_demo_widgets.c b/demos/widgets/lv_demo_widgets.c index 9878eb9c7..690b3f710 100644 --- a/demos/widgets/lv_demo_widgets.c +++ b/demos/widgets/lv_demo_widgets.c @@ -854,7 +854,7 @@ static void analytics_create(lv_obj_t * parent) lv_label_set_text(mbps_unit_label, "Mbps"); lv_anim_init(&a); - lv_anim_set_values(&a, 0, 60); + lv_anim_set_values(&a, 10, 60); lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE); lv_anim_set_exec_cb(&a, scale3_anim_cb); lv_anim_set_var(&a, needle); @@ -1617,9 +1617,8 @@ static void scale3_anim_cb(void * var, int32_t v) { LV_UNUSED(var); - int32_t angle = lv_map(v, 0, 60, 1350, 3600); lv_obj_t * needle = lv_obj_get_child(scale3, 0); - lv_image_set_rotation(needle, angle); + lv_scale_set_image_needle_value(scale3, needle, v); lv_obj_t * label = lv_obj_get_child(scale3, 1); lv_label_set_text_fmt(label, "%"LV_PRId32, v); diff --git a/examples/widgets/scale/lv_example_scale_3.c b/examples/widgets/scale/lv_example_scale_3.c index 4b92f8177..fa53093b0 100644 --- a/examples/widgets/scale/lv_example_scale_3.c +++ b/examples/widgets/scale/lv_example_scale_3.c @@ -1,27 +1,98 @@ #include "../../lv_examples.h" #if LV_USE_SCALE && LV_BUILD_EXAMPLES +LV_IMAGE_DECLARE(img_hand); + +lv_obj_t * needle_line; +lv_obj_t * needle_img; + +static void set_needle_line_value(void * obj, int32_t v) +{ + lv_scale_set_line_needle_value(obj, needle_line, 60, v); +} + +static void set_needle_img_value(void * obj, int32_t v) +{ + lv_scale_set_image_needle_value(obj, needle_img, v); +} + /** * A simple round scale */ void lv_example_scale_3(void) { - lv_obj_t * scale = lv_scale_create(lv_screen_active()); - lv_obj_set_size(scale, 150, 150); - lv_scale_set_mode(scale, LV_SCALE_MODE_ROUND_INNER); - lv_obj_set_style_bg_opa(scale, LV_OPA_COVER, 0); - lv_obj_set_style_bg_color(scale, lv_palette_lighten(LV_PALETTE_RED, 5), 0); - lv_obj_set_style_radius(scale, LV_RADIUS_CIRCLE, 0); - lv_obj_center(scale); + lv_obj_t * scale_line = lv_scale_create(lv_screen_active()); - lv_scale_set_label_show(scale, true); + lv_obj_set_size(scale_line, 150, 150); + lv_scale_set_mode(scale_line, LV_SCALE_MODE_ROUND_INNER); + lv_obj_set_style_bg_opa(scale_line, LV_OPA_COVER, 0); + lv_obj_set_style_bg_color(scale_line, lv_palette_lighten(LV_PALETTE_RED, 5), 0); + lv_obj_set_style_radius(scale_line, LV_RADIUS_CIRCLE, 0); + lv_obj_set_style_clip_corner(scale_line, true, 0); + lv_obj_align(scale_line, LV_ALIGN_LEFT_MID, LV_PCT(5), 0); - lv_scale_set_total_tick_count(scale, 31); - lv_scale_set_major_tick_every(scale, 5); + lv_scale_set_label_show(scale_line, true); - lv_scale_set_major_tick_length(scale, 10); - lv_scale_set_minor_tick_length(scale, 5); - lv_scale_set_range(scale, 10, 40); + lv_scale_set_total_tick_count(scale_line, 31); + lv_scale_set_major_tick_every(scale_line, 5); + + lv_scale_set_major_tick_length(scale_line, 10); + lv_scale_set_minor_tick_length(scale_line, 5); + lv_scale_set_range(scale_line, 10, 40); + + lv_scale_set_round_props(scale_line, 270, 135); + + needle_line = lv_line_create(scale_line); + + lv_obj_set_style_line_width(needle_line, 6, LV_PART_MAIN); + lv_obj_set_style_line_rounded(needle_line, true, LV_PART_MAIN); + + lv_anim_t anim_scale_line; + lv_anim_init(&anim_scale_line); + lv_anim_set_var(&anim_scale_line, scale_line); + lv_anim_set_exec_cb(&anim_scale_line, set_needle_line_value); + lv_anim_set_time(&anim_scale_line, 1000); + lv_anim_set_repeat_count(&anim_scale_line, LV_ANIM_REPEAT_INFINITE); + lv_anim_set_playback_time(&anim_scale_line, 1000); + lv_anim_set_values(&anim_scale_line, 10, 40); + lv_anim_start(&anim_scale_line); + + lv_obj_t * scale_img = lv_scale_create(lv_screen_active()); + + lv_obj_set_size(scale_img, 150, 150); + lv_scale_set_mode(scale_img, LV_SCALE_MODE_ROUND_INNER); + lv_obj_set_style_bg_opa(scale_img, LV_OPA_COVER, 0); + lv_obj_set_style_bg_color(scale_img, lv_palette_lighten(LV_PALETTE_RED, 5), 0); + lv_obj_set_style_radius(scale_img, LV_RADIUS_CIRCLE, 0); + lv_obj_set_style_clip_corner(scale_img, true, 0); + lv_obj_align(scale_img, LV_ALIGN_RIGHT_MID, LV_PCT(-5), 0); + + lv_scale_set_label_show(scale_img, true); + + lv_scale_set_total_tick_count(scale_img, 31); + lv_scale_set_major_tick_every(scale_img, 5); + + lv_scale_set_major_tick_length(scale_img, 10); + lv_scale_set_minor_tick_length(scale_img, 5); + lv_scale_set_range(scale_img, 10, 40); + + lv_scale_set_round_props(scale_img, 270, 135); + + /* image must point to the right. E.g. -O------>*/ + needle_img = lv_img_create(scale_img); + lv_image_set_src(needle_img, &img_hand); + lv_obj_align(needle_img, LV_ALIGN_CENTER, 47, -2); + lv_image_set_pivot(needle_img, 3, 4); + + lv_anim_t anim_scale_img; + lv_anim_init(&anim_scale_img); + lv_anim_set_var(&anim_scale_img, scale_img); + lv_anim_set_exec_cb(&anim_scale_img, set_needle_img_value); + lv_anim_set_time(&anim_scale_img, 1000); + lv_anim_set_repeat_count(&anim_scale_img, LV_ANIM_REPEAT_INFINITE); + lv_anim_set_playback_time(&anim_scale_img, 1000); + lv_anim_set_values(&anim_scale_img, 10, 40); + lv_anim_start(&anim_scale_img); } #endif diff --git a/src/widgets/scale/lv_scale.c b/src/widgets/scale/lv_scale.c index 9ea85585e..43a65710b 100644 --- a/src/widgets/scale/lv_scale.c +++ b/src/widgets/scale/lv_scale.c @@ -182,6 +182,88 @@ void lv_scale_set_round_props(lv_obj_t * obj, uint32_t angle_range, int32_t rota lv_obj_invalidate(obj); } +void lv_scale_set_line_needle_value(lv_obj_t * obj, lv_obj_t * needle_line, int32_t needle_length, + int32_t value) +{ + int32_t angle; + int32_t scale_width, scale_height; + int32_t actual_needle_length; + int32_t needle_length_x, needle_length_y; + static lv_point_precise_t needle_line_points[2]; + + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_scale_t * scale = (lv_scale_t *)obj; + if((scale->mode != LV_SCALE_MODE_ROUND_INNER) && + (scale->mode != LV_SCALE_MODE_ROUND_OUTER)) { + return; + } + + lv_obj_align(needle_line, LV_ALIGN_TOP_LEFT, 0, 0); + + scale_width = lv_obj_get_style_width(obj, LV_PART_MAIN); + scale_height = lv_obj_get_style_height(obj, LV_PART_MAIN); + + if(scale_width != scale_height) { + return; + } + + if(needle_length >= scale_width / 2) { + actual_needle_length = scale_width / 2; + } + else if(needle_length >= 0) { + actual_needle_length = needle_length; + } + else if(needle_length + scale_width / 2 < 0) { + actual_needle_length = 0; + } + else { + actual_needle_length = scale_width / 2 + needle_length; + } + + if(value < scale->range_min) { + angle = 0; + } + else if(value > scale->range_max) { + angle = scale->angle_range; + } + else { + angle = scale->angle_range * (value - scale->range_min) / (scale->range_max - scale->range_min); + } + + needle_length_x = (actual_needle_length * lv_trigo_cos(scale->rotation + angle)) >> LV_TRIGO_SHIFT; + needle_length_y = (actual_needle_length * lv_trigo_sin(scale->rotation + angle)) >> LV_TRIGO_SHIFT; + + needle_line_points[0].x = scale_width / 2; + needle_line_points[0].y = scale_height / 2; + needle_line_points[1].x = scale_width / 2 + needle_length_x; + needle_line_points[1].y = scale_height / 2 + needle_length_y; + + lv_line_set_points(needle_line, needle_line_points, 2); +} + +void lv_scale_set_image_needle_value(lv_obj_t * obj, lv_obj_t * needle_img, int32_t value) +{ + int32_t angle; + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_scale_t * scale = (lv_scale_t *)obj; + if((scale->mode != LV_SCALE_MODE_ROUND_INNER) && + (scale->mode != LV_SCALE_MODE_ROUND_OUTER)) { + return; + } + + if(value < scale->range_min) { + angle = 0; + } + else if(value > scale->range_max) { + angle = scale->angle_range; + } + else { + angle = scale->angle_range * (value - scale->range_min) / (scale->range_max - scale->range_min); + } + + lv_image_set_rotation(needle_img, (scale->rotation + angle) * 10); +} + void lv_scale_set_text_src(lv_obj_t * obj, const char * txt_src[]) { LV_ASSERT_OBJ(obj, MY_CLASS); diff --git a/src/widgets/scale/lv_scale.h b/src/widgets/scale/lv_scale.h index a6b9fae4f..ffd634b91 100644 --- a/src/widgets/scale/lv_scale.h +++ b/src/widgets/scale/lv_scale.h @@ -18,6 +18,8 @@ extern "C" { #if LV_USE_SCALE != 0 #include "../../core/lv_obj.h" +#include "../line/lv_line.h" +#include "../image/lv_image.h" /********************* * DEFINES @@ -169,6 +171,27 @@ void lv_scale_set_range(lv_obj_t * obj, int32_t min, int32_t max); */ void lv_scale_set_round_props(lv_obj_t * obj, uint32_t angle_range, int32_t rotation); +/** + * Point the needle to the corresponding value through the line + * @param obj pointer to a scale object + * @param needle_line needle_line of the scale + * @param needle_length length of the needle + * needle_length>0 needle_length=needle_length; + * needle_length<0 needle_length=radius-|needle_length|; + * @param value needle to point to the corresponding value + */ +void lv_scale_set_line_needle_value(lv_obj_t * obj, lv_obj_t * needle_line, int32_t needle_length, + int32_t value); + +/** + * Point the needle to the corresponding value through the image, + image must point to the right. E.g. -O------> + * @param obj pointer to a scale object + * @param needle_img needle_img of the scale + * @param value needle to point to the corresponding value + */ +void lv_scale_set_image_needle_value(lv_obj_t * obj, lv_obj_t * needle_img, int32_t value); + /** * Set custom text source for major ticks labels * @param obj pointer to a scale object