How to make a music player with a rotating record?

I directly create a canvas in the page, and create an animation with following code:

static void func(void * var, lv_anim_value_t value)
{
    lv_obj_t * canvas = (lv_obj_t *)var;
    lv_canvas_rotate(canvas, &qq, value, 0, 0, CANVAS_WIDTH / 2, CANVAS_HEIGHT / 2);
}
lv_obj_t * canvas = lv_canvas_create(sb, NULL);
static lv_color_t buffer[LV_CANVAS_BUF_SIZE_TRUE_COLOR_ALPHA(CANVAS_WIDTH, CANVAS_HEIGHT)];
lv_canvas_set_buffer(canvas, buffer, CANVAS_WIDTH, CANVAS_HEIGHT, LV_IMG_CF_TRUE_COLOR_ALPHA);
lv_canvas_draw_img(canvas, 10, 10, &qq, &style1);
//lv_canvas_rotate(canvas, &qq, 0, 0, 0, CANVAS_WIDTH / 2, CANVAS_HEIGHT / 2);

lv_anim_t a;
lv_anim_set_exec_cb(&a, canvas, func);    /*Set the animator function and variable to animate*/ 
lv_anim_set_time(&a, 10*1000, 0);
lv_anim_set_values(&a, 0, 359);             /*Set start and end values. E.g. 0, 150*/
lv_anim_set_path_cb(&a, lv_anim_path_linear);   /*Set path from `lv_anim_path_...` functions or a custom one.*/
//lv_anim_set_ready_cb(&a, ready_cb);             /*Set a callback to call then animation is ready. (Optional)*/
//lv_anim_set_playback(&a, 0);            /*Enable playback of teh animation with `wait_time` delay*/
lv_anim_set_repeat(&a, 0);              /*Enable repeat of teh animation with `wait_time` delay. Can be compiled with playback*/

lv_anim_create(&a);      

The problem is the image rotating take too much times, cause other controls become a little slow(response delays).

how to solve it?? Maybe i can put the rotating operation into another worker thread?
Is there any better way??

Define 4 or 8 images and update the canvas with the new image. That’s a map, pretty fast vs a sin and cos on each pixel

You can probably just use an lv_img if you’re only changing images; no need to use the full-fledged canvas for something that simple.

how to rotating a lv_img object??

But this may not be smooth enough

Well, this is a classic memory vs speed issue.

Rotation of a bitmap requires a lot of math, so it is slow (Unless you are on something with a GPU).
Now there are ways to make it faster, like to have lookups for sin/cos tables, but its gonna be slow.

Option 2 - Store the bitmaps and cycle between them. Depending on how “Smooth” you want it you could have 4, 8, 4096 or whatever number, but that has a memory cost.

how about rotating the bitmap in another worker/helper thread but not the ui thread??

You can call lv_canvas_rotate in another thread if you which. Just be sure to use a mutex around lv_task_handler and lv_canvas_rotate.

It’s still going to look sluggish, because (from what I can tell) your CPU is too slow to rotate the image at a reasonable frame rate. The 16-32 ms you’ll have between frames doesn’t seem like it’s going to be enough.

I think it would be better to just use a few premade images. Another option is to come up with some clever way of faking the rotation. For example, on a website, I might do something like:

  • Draw a background image of a record.
  • Draw a slightly darker/lighter line at a given angle with a halo around it.
  • Repeat 15 times a second or whatever speed you need.

This will be a lot faster than rotating the whole image because you only have to rotate the line (and it’s not really a rotation from LittlevGL’s perspective).

in my opinion, the user interface becomes sluggish is because the UI thread was blocked by(busy with) the image rotating computation, and unable to respond user input in time

That’s probably because your processor is too slow (or barely fast enough). I would thus suggest that you fake the effect with either multiple images or the trick I suggested above

Multiple threads won’t help you because you have to guard LittlevGL calls with a mutex anyways.