212 lines
6.6 KiB
C
212 lines
6.6 KiB
C
#include "lvgl.h"
|
|
#include "speedmeter.h"
|
|
#include "speedmeter_private.h"
|
|
#include "src/core/lv_obj_class_private.h"
|
|
|
|
#define MY_CLASS (&lv_speedmeter_class)
|
|
|
|
static void lv_speedmeter_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj);
|
|
static void lv_speedmeter_event(const lv_obj_class_t* class_p, lv_event_t* e);
|
|
|
|
|
|
const lv_obj_class_t lv_speedmeter_class = {
|
|
.constructor_cb = lv_speedmeter_constructor,
|
|
.event_cb = lv_speedmeter_event,
|
|
.width_def = LV_SIZE_CONTENT,
|
|
.height_def = LV_SIZE_CONTENT,
|
|
.instance_size = sizeof(lv_speedmeter_t),
|
|
.base_class = &lv_obj_class,
|
|
.name = "lv_speedmeter",
|
|
LV_PROPERTY_CLASS_FIELDS(speedmeter, SPEEDMETER)
|
|
};
|
|
|
|
|
|
static void lv_speedmeter_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj) {
|
|
LV_UNUSED(class_p);
|
|
LV_TRACE_OBJ_CREATE("begin");
|
|
|
|
lv_speedmeter_t* speedmeter = (lv_speedmeter_t*)obj;
|
|
|
|
speedmeter->speed = 0;
|
|
|
|
lv_obj_remove_flag(obj, LV_OBJ_FLAG_CLICKABLE);
|
|
|
|
LV_TRACE_OBJ_CREATE("finished");
|
|
}
|
|
|
|
static void lv_speedmeter_event(const lv_obj_class_t* class_p, lv_event_t* e) {
|
|
LV_UNUSED(class_p);
|
|
|
|
lv_result_t res;
|
|
|
|
res = lv_obj_event_base(MY_CLASS, e);
|
|
if (res != LV_RESULT_OK) return;
|
|
}
|
|
|
|
static void speed_arc_value_changed(lv_event_t* event) {
|
|
lv_obj_t* arc = lv_event_get_target(event);
|
|
|
|
int32_t value = lv_arc_get_value(arc);
|
|
|
|
lv_speedmeter_t* self = (lv_speedmeter_t*)lv_event_get_user_data(event);
|
|
float speed = value * self->max_speed / 100.0;
|
|
lv_label_set_text_fmt(self->speed_label, "%0.1f", speed);
|
|
|
|
}
|
|
|
|
lv_obj_t* lv_speedmeter_create(lv_obj_t* parent, int max_speed, const char* unit) {
|
|
LV_LOG_INFO("begin");
|
|
|
|
lv_obj_t* obj = lv_obj_class_create_obj(MY_CLASS, parent);
|
|
lv_obj_class_init_obj(obj);
|
|
|
|
lv_obj_set_size(obj, lv_pct(100), lv_pct(100));
|
|
lv_obj_update_layout(obj);
|
|
|
|
|
|
lv_speedmeter_t* self = (lv_speedmeter_t*)obj;
|
|
|
|
self->max_speed = max_speed;
|
|
|
|
lv_obj_t* arc = lv_arc_create(obj);
|
|
lv_obj_remove_flag(arc, LV_OBJ_FLAG_CLICKABLE);
|
|
lv_coord_t size = LV_MIN(
|
|
lv_obj_get_width(obj),
|
|
lv_obj_get_height(obj)
|
|
) * 0.8;
|
|
lv_obj_set_size(arc, size, size);
|
|
lv_obj_remove_style(arc, NULL, LV_PART_KNOB);
|
|
lv_obj_set_style_arc_color(arc, lv_color_hex(0x367BF1), LV_PART_INDICATOR);
|
|
lv_obj_set_style_arc_color(arc, lv_color_hex(0x21242A), LV_PART_MAIN);
|
|
lv_obj_set_style_arc_width(arc, 12, LV_PART_INDICATOR);
|
|
lv_obj_set_style_arc_width(arc, 12, LV_PART_MAIN);
|
|
lv_obj_center(arc);
|
|
lv_obj_update_layout(arc);
|
|
|
|
self->speed_arc = arc;
|
|
|
|
LV_FONT_DECLARE(lv_font_din_26);
|
|
|
|
|
|
//速度标签
|
|
lv_obj_t* speed_label = lv_label_create(obj);
|
|
lv_obj_set_align(speed_label, LV_ALIGN_CENTER);
|
|
lv_label_set_text(speed_label, "0.0");
|
|
LV_FONT_DECLARE(lv_font_din_42);
|
|
lv_obj_set_style_text_font(speed_label, &lv_font_din_42, 0);
|
|
lv_obj_set_style_text_color(speed_label, lv_color_hex(0xffffff), 0);
|
|
|
|
self->speed_label = speed_label;
|
|
|
|
|
|
|
|
lv_obj_t* speed_unit_label = lv_label_create(obj);
|
|
|
|
lv_obj_align(speed_unit_label, LV_ALIGN_CENTER, 0, 30);
|
|
lv_obj_set_style_text_font(speed_unit_label, &lv_font_din_26, 0);
|
|
if (unit == NULL || strnlen(unit, 10) == 0) {
|
|
lv_label_set_text(speed_unit_label, "km/h");
|
|
}
|
|
else {
|
|
lv_label_set_text(speed_unit_label, unit);
|
|
}
|
|
lv_obj_set_style_text_color(speed_unit_label, lv_color_hex(0xB4BCC8), 0);
|
|
|
|
self->speed_unit_label = speed_unit_label;
|
|
|
|
lv_obj_add_event_cb(arc, speed_arc_value_changed, LV_EVENT_VALUE_CHANGED, self);
|
|
lv_arc_set_value(arc, 0);
|
|
|
|
// 获取角度范围
|
|
int32_t start_angle = lv_arc_get_bg_angle_start(arc);
|
|
int32_t end_angle = lv_arc_get_bg_angle_end(arc);
|
|
|
|
int32_t angle_range = (end_angle >= start_angle)
|
|
? (end_angle - start_angle)
|
|
: (360 - start_angle + end_angle);
|
|
|
|
// 获取中心点
|
|
lv_coord_t cx = lv_obj_get_width(arc) / 2;
|
|
lv_coord_t cy = lv_obj_get_height(arc) / 2;
|
|
|
|
// 半径(用中心半径更准)
|
|
lv_coord_t radius = LV_MIN(lv_obj_get_width(arc), lv_obj_get_height(arc)) / 2;
|
|
|
|
|
|
// 画刻度
|
|
static lv_point_precise_t line_points[(90 / 5 + 1) * 2] = { {0,0} };
|
|
for (int speed = 0; speed <= max_speed; speed += 5) {
|
|
|
|
int32_t angle = start_angle + (angle_range * speed) / max_speed;
|
|
if (angle >= 360) angle -= 360;
|
|
|
|
int32_t cos_v = lv_trigo_cos(angle);
|
|
int32_t sin_v = lv_trigo_sin(angle);
|
|
|
|
lv_obj_t* line = lv_line_create(arc);
|
|
|
|
lv_coord_t inner_r = radius; // 刻度内侧
|
|
lv_coord_t outer_r = radius; // 刻度外侧
|
|
|
|
// 粗细区分(10为大刻度)
|
|
if (speed % 10 == 0) {
|
|
lv_obj_set_style_line_width(line, 3, 0);
|
|
inner_r -= 20;
|
|
if (speed != 0 && speed != max_speed)
|
|
{
|
|
outer_r -= 13;
|
|
}
|
|
lv_obj_set_style_line_color(line, lv_color_hex(0xffffff), 0);
|
|
}
|
|
else {
|
|
lv_obj_set_style_line_width(line, 2, 0);
|
|
outer_r -= 14;
|
|
inner_r -= 18;
|
|
lv_obj_set_style_line_color(line, lv_color_hex(0x21242A), 0);
|
|
}
|
|
|
|
// 起点
|
|
lv_point_precise_t* p = line_points + (speed / 5) * 2;
|
|
p[0].x = cx + (inner_r * cos_v) / 32767;
|
|
p[0].y = cy + (inner_r * sin_v) / 32767;
|
|
|
|
// 终点
|
|
p[1].x = cx + (outer_r * cos_v) / 32767;
|
|
p[1].y = cy + (outer_r * sin_v) / 32767;
|
|
|
|
if (speed % 10 == 0) {
|
|
lv_coord_t text_r = inner_r - 15;
|
|
|
|
lv_coord_t label_x = cx + (text_r * cos_v) / 32767;
|
|
lv_coord_t label_y = cy + (text_r * sin_v) / 32767;
|
|
lv_obj_t* label = lv_label_create(arc);
|
|
lv_obj_set_style_text_font(label, &lv_font_din_26, 0);
|
|
lv_obj_set_style_text_color(label, lv_color_hex(0xB4BCC8), 0);
|
|
lv_label_set_text_fmt(label, "%d", speed);
|
|
lv_obj_update_layout(label);
|
|
lv_obj_set_pos(label, label_x - lv_obj_get_width(label) / 2, label_y - lv_obj_get_height(label) / 2);
|
|
}
|
|
|
|
lv_line_set_points(line, p, 2);
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
void lv_speedmeter_set_speed(lv_obj_t* obj, float speed) {
|
|
lv_speedmeter_t* self = (lv_speedmeter_t*)obj;
|
|
self->speed = speed;
|
|
int arc_value = (int)(self->speed / self->max_speed * 100.0);
|
|
lv_arc_set_value(self->speed_arc, arc_value);
|
|
lv_obj_send_event(self->speed_arc, LV_EVENT_VALUE_CHANGED, NULL);
|
|
}
|
|
|
|
float lv_speedmeter_get_speed(lv_obj_t* obj) {
|
|
lv_speedmeter_t* self = (lv_speedmeter_t*)obj;
|
|
return self->speed;
|
|
}
|
|
|
|
void lv_speedmeter_set_unit_label(lv_obj_t* obj, const char* label) {
|
|
lv_speedmeter_t* self = (lv_speedmeter_t*)obj;
|
|
lv_label_set_text(self->speed_unit_label, label);
|
|
}
|