Multiple shadows per object

ln CSS we can achieve very impressive visual results by using multiple shadows on a single box.
I have no idea how hard it would be to add this to lvgl but it would be an awesome feature for people coming to lvgl with some CSS foundations.
See this for an example that uses a light and dark shadow:
for more ‘creative’ uses see:
if that ould make it feasible, limiting the number of shadows to some n>1 i.e. 2 or 3 would solve a vast majority of use-cases


 Label2 = lv_label_create(Screen1, NULL);
    lv_label_set_long_mode(Label2, LV_LABEL_LONG_DOT);
    lv_label_set_align(Label2, LV_LABEL_ALIGN_CENTER);
    lv_label_set_text(Label2, "\n");
    lv_obj_set_size(Label2, 125, 66);  // force: 10
    lv_obj_set_click(Label2, true);
    lv_obj_set_hidden(Label2, false);
    lv_obj_clear_state(Label2, LV_STATE_DISABLED);
    lv_obj_set_drag(Label2, false);
    lv_obj_set_style_local_bg_color(Label2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT,
                                    lv_color_hex(241 * 256 * 256 + 241 * 256 + 241));
    lv_obj_set_style_local_bg_opa(Label2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 255);
    lv_obj_set_style_local_bg_main_stop(Label2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
    lv_obj_set_style_local_bg_grad_stop(Label2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 255);
    lv_obj_set_style_local_radius(Label2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 10);
    lv_obj_set_style_local_shadow_color(Label2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT,
                                        lv_color_hex(40 * 256 * 256 + 40 * 256 + 40));
    lv_obj_set_style_local_shadow_opa(Label2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 100);
    lv_obj_set_style_local_shadow_width(Label2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 16);
    lv_obj_set_style_local_shadow_spread(Label2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 2);
    lv_obj_set_style_local_shadow_ofs_x(Label2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 5);
    lv_obj_set_style_local_shadow_ofs_y(Label2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 5);

    lv_obj_align(Label2, Screen1, LV_ALIGN_CENTER, 10, -1); // force: 125

    Label2_copy = lv_label_create(Screen1, NULL);
    lv_label_set_long_mode(Label2_copy, LV_LABEL_LONG_DOT);
    lv_label_set_align(Label2_copy, LV_LABEL_ALIGN_CENTER);
    lv_label_set_text(Label2_copy, "\nTest\nShadow");
    lv_obj_set_size(Label2_copy, 125, 66);  // force: 10
    lv_obj_set_click(Label2_copy, true);
    lv_obj_set_hidden(Label2_copy, false);
    lv_obj_clear_state(Label2_copy, LV_STATE_DISABLED);
    lv_obj_set_drag(Label2_copy, false);
    lv_obj_set_style_local_text_color(Label2_copy, LV_BTN_PART_MAIN, LV_STATE_DEFAULT,
                                      lv_color_hex(49 * 256 * 256 + 49 * 256 + 49));
    lv_obj_set_style_local_text_opa(Label2_copy, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 255);
    lv_obj_set_style_local_text_font(Label2_copy, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_font_montserrat_16);
    lv_obj_set_style_local_bg_color(Label2_copy, LV_BTN_PART_MAIN, LV_STATE_DEFAULT,
                                    lv_color_hex(241 * 256 * 256 + 241 * 256 + 241));
    lv_obj_set_style_local_bg_opa(Label2_copy, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 255);
    lv_obj_set_style_local_bg_main_stop(Label2_copy, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
    lv_obj_set_style_local_bg_grad_stop(Label2_copy, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 255);
    lv_obj_set_style_local_radius(Label2_copy, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 10);
    lv_obj_set_style_local_shadow_color(Label2_copy, LV_BTN_PART_MAIN, LV_STATE_DEFAULT,
                                        lv_color_hex(255 * 256 * 256 + 255 * 256 + 255));
    lv_obj_set_style_local_shadow_opa(Label2_copy, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 255);
    lv_obj_set_style_local_shadow_width(Label2_copy, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 16);
    lv_obj_set_style_local_shadow_spread(Label2_copy, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 2);
    lv_obj_set_style_local_shadow_ofs_x(Label2_copy, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, -5);
    lv_obj_set_style_local_shadow_ofs_y(Label2_copy, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, -5);

    lv_obj_align(Label2_copy, Screen1, LV_ALIGN_CENTER, 10, -1); // force: 125

Is just 2 labels, and you can add a handler if want work as a button

1 Like

I have many ideas in mind to improve the SW rendering engine. Making effects more versatile is also among them. :slight_smile:

I was thinking about creating something like an “effect stack” in which you can enumerate effects that LVGL applies when the object is drawn. In v8 it can be implemented as a plugin/module (i.e. without modifying the renderer) by using the draw events. See this example. Here a Switch is “just drawn” when the cell of the table is drawn. We can do the same with a button and render any number of extra shadows.

1 Like

Great example, thanks for sharing!

1 Like

I was aware of this workaround. It works great until we have multiple shadows for a single label, still impressive and thanks for the effort, Its a great example of getting somewhere via many ways.

Still i think it would be awesome if you would simply have to option to add multiple shadows.

Thanks you for this great library.
My request is just add a handler for labels in EdgeLine, so not need use button+label+handler , but just label+handler