However, the functionality and power of the LVGL library has been swallowed up by ease of use, comparable to tft_eSPI or lovyanGFX.
I draw triangles on the canvas with primitives, and make the border with lines.
The code for this is:
// Function for drawing triangles and rendering them on a canvas with rotation capability
void draw_triangle(void)
{
#define CANVAS_WIDTH 210 // Define the width of the canvas
#define CANVAS_HEIGHT 60 // Define the height of the canvas
#define PLANE_HEIGH 50 // Define the height for the triangle base
/* Create a buffer for the canvas */
LV_DRAW_BUF_DEFINE_STATIC(draw_buf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888);
// Alternative formats commented out due to limitations
LV_DRAW_BUF_INIT_STATIC(draw_buf); // Initialize the drawing buffer
/* Create a canvas and initialize its palette */
lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); // Create canvas object
lv_canvas_set_draw_buf(canvas, &draw_buf); // Attach drawing buffer to the canvas
// Uncomment to set a background color; currently transparent
lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_TRANSP); // Fill canvas background
lv_obj_center(canvas); // Center the canvas in the active screen
// Create a layer for drawing on the canvas
lv_layer_t layer;
lv_canvas_init_layer(canvas, &layer);
// Create an additional layer on the canvas that renders everything as an image and allows rotation
lv_image_dsc_t img; // Image descriptor for the drawn content
lv_draw_buf_to_image(&draw_buf, &img); // Convert draw buffer to image
lv_draw_image_dsc_t img_dsc; // Image description structure
lv_draw_image_dsc_init(&img_dsc); // Initialize image description
img_dsc.rotation = 200; // Set rotation angle (20 degrees)
img_dsc.src = &img; // Source of the image
img_dsc.pivot.x = CANVAS_WIDTH / 2; // Set pivot point for rotation
img_dsc.pivot.y = CANVAS_HEIGHT / 2;
// Define the left light triangle
lv_draw_triangle_dsc_t tri_dsc_1;
lv_draw_triangle_dsc_init(&tri_dsc_1); // Initialize triangle description
// Set vertices of the triangle
tri_dsc_1.p[0].x = 10;
tri_dsc_1.p[0].y = PLANE_HEIGH;
tri_dsc_1.p[1].x = 30;
tri_dsc_1.p[1].y = PLANE_HEIGH;
tri_dsc_1.p[2].x = CANVAS_WIDTH / 2;
tri_dsc_1.p[2].y = 10;
// Setting color and opacity for the triangle
tri_dsc_1.color = lv_palette_main(LV_PALETTE_YELLOW);
tri_dsc_1.opa = 255; // Set the overall opacity to 100%
// Define the left dark triangle
lv_draw_triangle_dsc_t tri_dsc_2;
lv_draw_triangle_dsc_init(&tri_dsc_2); // Initialize triangle description
// Set vertices of the triangle
tri_dsc_2.p[0].x = 30;
tri_dsc_2.p[0].y = PLANE_HEIGH;
tri_dsc_2.p[1].x = CANVAS_WIDTH / 2;
tri_dsc_2.p[1].y = 10;
tri_dsc_2.p[2].x = 45;
tri_dsc_2.p[2].y = PLANE_HEIGH;
// Setting color and opacity for the triangle
tri_dsc_2.color = lv_palette_main(LV_PALETTE_GREY);
tri_dsc_2.opa = 255; // Set the overall opacity to 100%
// Define the right dark triangle
lv_draw_triangle_dsc_t tri_dsc_3;
lv_draw_triangle_dsc_init(&tri_dsc_3); // Initialize triangle description
// Set vertices of the triangle
tri_dsc_3.p[0].x = 180;
tri_dsc_3.p[0].y = 50;
tri_dsc_3.p[1].x = CANVAS_WIDTH / 2;
tri_dsc_3.p[1].y = 10;
tri_dsc_3.p[2].x = 165;
tri_dsc_3.p[2].y = PLANE_HEIGH;
// Setting color and opacity for the triangle
tri_dsc_3.color = lv_palette_main(LV_PALETTE_GREY);
tri_dsc_3.opa = 255; // Set the overall opacity to 100%
// Right light triangle
lv_draw_triangle_dsc_t tri_dsc_4;
lv_draw_triangle_dsc_init(&tri_dsc_4);
tri_dsc_4.p[0].x = CANVAS_WIDTH / 2;
tri_dsc_4.p[0].y = 10;
tri_dsc_4.p[1].x = 200;
tri_dsc_4.p[1].y = PLANE_HEIGH;
tri_dsc_4.p[2].x = 180;
tri_dsc_4.p[2].y = PLANE_HEIGH;
// tri_dsc_4.color = lv_color_hex(0xFFFF00);
tri_dsc_4.color = lv_palette_main(LV_PALETTE_YELLOW);
// Triangle transparency, canvas transparency is set above in the code
tri_dsc_4.opa = 255; /* Set the overall opacity to 50% */
/* // Border, currently only around the canvas
static lv_style_t style_plane_g5;
lv_style_init(&style_plane_g5);
// Outline
lv_style_set_outline_width(&style_plane_g5, 2);
// lv_style_set_outline_color(&style_plane_g5, lv_palette_main(LV_PALETTE_GREY));
lv_style_set_outline_color(&style_plane_g5, lv_color_hex(0x000000));
lv_style_set_outline_pad(&style_plane_g5, 4);
lv_obj_add_style(canvas, &style_plane_g5, 0); */
// Drawing lines on the canvas for outlining the airplane
lv_draw_line_dsc_t line1; // Lower left line
lv_draw_line_dsc_init(&line1);
// line1.color = lv_palette_main(LV_PALETTE_RED);
line1.color = lv_color_hex(0x000000);
line1.width = 1;
line1.round_end = 1;
line1.round_start = 1;
line1.p1.x = tri_dsc_1.p[0].x;
line1.p1.y = tri_dsc_1.p[0].y;
line1.p2.x = tri_dsc_2.p[2].x;
line1.p2.y = tri_dsc_2.p[2].y;
lv_draw_line_dsc_t line2; // Diagonal left line
lv_draw_line_dsc_init(&line2);
// line1.color = lv_palette_main(LV_PALETTE_RED);
line2.color = lv_color_hex(0x000000);
line2.width = 1;
line2.round_end = 1;
line2.round_start = 1;
line2.p1.x = tri_dsc_2.p[2].x;
line2.p1.y = tri_dsc_2.p[2].y;
line2.p2.x = tri_dsc_1.p[2].x;
line2.p2.y = tri_dsc_1.p[2].y;
lv_draw_line_dsc_t line3; // Diagonal right line
lv_draw_line_dsc_init(&line3);
// line1.color = lv_palette_main(LV_PALETTE_RED);
line3.color = lv_color_hex(0x000000);
line3.width = 1;
line3.round_end = 1;
line3.round_start = 1;
line3.p1.x = tri_dsc_3.p[2].x;
line3.p1.y = tri_dsc_3.p[2].y;
line3.p2.x = tri_dsc_4.p[0].x;
line3.p2.y = tri_dsc_4.p[0].y;
lv_draw_line_dsc_t line4; // Lower right line
lv_draw_line_dsc_init(&line4);
// line1.color = lv_palette_main(LV_PALETTE_RED);
line4.color = lv_color_hex(0x000000);
line4.width = 1;
line4.round_end = 1;
line4.round_start = 1;
line4.p1.x = tri_dsc_3.p[2].x;
line4.p1.y = tri_dsc_3.p[2].y;
line4.p2.x = tri_dsc_4.p[1].x;
line4.p2.y = tri_dsc_4.p[1].y;
/* lv_draw_line_dsc_t line1 = {
.p1 = tri_dsc_2.p[1],
.p2 = tri_dsc_2.p[2],
.width=2,
.round_start=1,
.round_end=1,
.color=lv_color_hex(0xFF0000),
// .color=lv_palette_main(LV_PALETTE_RED),
.opa=255
}
lv_draw_line_dsc_init(&line1); */
// Rendering triangles on the canvas as images
lv_draw_triangle(&layer, &tri_dsc_1);
lv_draw_triangle(&layer, &tri_dsc_2);
lv_draw_triangle(&layer, &tri_dsc_3);
lv_draw_triangle(&layer, &tri_dsc_4);
// Rendering lines on the canvas as images
lv_draw_line(&layer, &line1);
lv_draw_line(&layer, &line2);
lv_draw_line(&layer, &line3);
lv_draw_line(&layer, &line4);
// This part sets the coordinates for the image and essentially outputs everything to the canvas as an image - maybe?
lv_area_t coords_img = {0, 0, CANVAS_WIDTH - 1, CANVAS_HEIGHT - 1};
// lv_area_t coords_img = {CANVAS_WIDTH / 2, CANVAS_HEIGHT / 2, CANVAS_WIDTH - 1, CANVAS_HEIGHT - 1};
// Generates the image
// lv_draw_image(&layer, &img_dsc, &coords_img);
lv_canvas_finish_layer(canvas, &layer);
}
Everything is fine if I don’t rotate the canvas
But everything is bad when I rotate it
My hopes of creating something serious based on LVGL are fading with each passing week ![]()
tft_eSPI allowed drawing with primitives on Sprite (analog of canvas) with 50 FPS without much effort ![]()
Unfortunately, the problem remains for several years…


