mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-28 07:03:00 +08:00
feat(anim): add a pause method (#7583)
This commit is contained in:
parent
124b2e268d
commit
e028ee985c
@ -293,6 +293,18 @@ This function returns a Boolean value indicating whether any *live, running*
|
||||
Animations were deleted.
|
||||
|
||||
|
||||
.. _animation_pause:
|
||||
|
||||
Pausing Animations
|
||||
******************
|
||||
|
||||
If you kept a copy of the pointer returned by :cpp:func:`lv_anim_start`,
|
||||
you can pause the running animation using :cpp:expr:`lv_anim_pause(animation)` and then resume it
|
||||
using :cpp:expr:`lv_anim_resume(animation)`.
|
||||
|
||||
:cpp:expr:`lv_anim_pause_for(animation, milliseconds)`
|
||||
is also available if you wish for the animation to resume automatically after.
|
||||
|
||||
|
||||
.. _animations_timeline:
|
||||
|
||||
|
@ -15,6 +15,11 @@ Cubic Bezier animation
|
||||
.. lv_example:: anim/lv_example_anim_3
|
||||
:language: c
|
||||
|
||||
Pause animation
|
||||
----------------------
|
||||
.. lv_example:: anim/lv_example_anim_4
|
||||
:language: c
|
||||
|
||||
Animation timeline
|
||||
------------------
|
||||
.. lv_example:: anim/lv_example_anim_timeline_1
|
||||
|
@ -28,6 +28,7 @@ extern "C" {
|
||||
void lv_example_anim_1(void);
|
||||
void lv_example_anim_2(void);
|
||||
void lv_example_anim_3(void);
|
||||
void lv_example_anim_4(void);
|
||||
void lv_example_anim_timeline_1(void);
|
||||
|
||||
/**********************
|
||||
|
60
examples/anim/lv_example_anim_4.c
Normal file
60
examples/anim/lv_example_anim_4.c
Normal file
@ -0,0 +1,60 @@
|
||||
#include "../lv_examples.h"
|
||||
#if LV_BUILD_EXAMPLES && LV_USE_SWITCH
|
||||
|
||||
static void anim_x_cb(void * var, int32_t v)
|
||||
{
|
||||
lv_obj_set_x(var, v);
|
||||
}
|
||||
|
||||
static void timer_cb(lv_timer_t * timer)
|
||||
{
|
||||
|
||||
lv_anim_t * anim = lv_timer_get_user_data(timer);
|
||||
lv_anim_pause_for(anim, 1000);
|
||||
lv_timer_delete(timer);
|
||||
}
|
||||
static void sw_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_obj_t * sw = lv_event_get_target(e);
|
||||
lv_obj_t * label = lv_event_get_user_data(e);
|
||||
|
||||
if(lv_obj_has_state(sw, LV_STATE_CHECKED)) {
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, label);
|
||||
lv_anim_set_values(&a, lv_obj_get_x(label), 100);
|
||||
lv_anim_set_duration(&a, 500);
|
||||
lv_anim_set_exec_cb(&a, anim_x_cb);
|
||||
lv_anim_set_path_cb(&a, lv_anim_path_overshoot);
|
||||
lv_timer_create(timer_cb, 200, lv_anim_start(&a));
|
||||
}
|
||||
else {
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, label);
|
||||
lv_anim_set_values(&a, lv_obj_get_x(label), -lv_obj_get_width(label));
|
||||
lv_anim_set_duration(&a, 500);
|
||||
lv_anim_set_exec_cb(&a, anim_x_cb);
|
||||
lv_anim_set_path_cb(&a, lv_anim_path_ease_in);
|
||||
lv_timer_create(timer_cb, 200, lv_anim_start(&a));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Start animation on an event
|
||||
*/
|
||||
void lv_example_anim_4(void)
|
||||
{
|
||||
lv_obj_t * label = lv_label_create(lv_screen_active());
|
||||
lv_label_set_text(label, "Hello animations!");
|
||||
lv_obj_set_pos(label, 100, 10);
|
||||
|
||||
lv_obj_t * sw = lv_switch_create(lv_screen_active());
|
||||
lv_obj_center(sw);
|
||||
lv_obj_add_state(sw, LV_STATE_CHECKED);
|
||||
lv_obj_add_event_cb(sw, sw_event_cb, LV_EVENT_VALUE_CHANGED, label);
|
||||
}
|
||||
|
||||
#endif
|
@ -44,6 +44,7 @@ static void anim_mark_list_change(void);
|
||||
static void anim_completed_handler(lv_anim_t * a);
|
||||
static int32_t lv_anim_path_cubic_bezier(const lv_anim_t * a, int32_t x1,
|
||||
int32_t y1, int32_t x2, int32_t y2);
|
||||
static void lv_anim_pause_for_internal(lv_anim_t * a, uint32_t ms);
|
||||
static void resolve_time(lv_anim_t * a);
|
||||
static bool remove_concurrent_anims(lv_anim_t * a_current);
|
||||
static void remove_anim(void * a);
|
||||
@ -104,6 +105,7 @@ lv_anim_t * lv_anim_start(const lv_anim_t * a)
|
||||
if(a->var == a) new_anim->var = new_anim;
|
||||
new_anim->run_round = state.anim_run_round;
|
||||
new_anim->last_timer_run = lv_tick_get();
|
||||
new_anim->is_paused = false;
|
||||
|
||||
/*Set the start value*/
|
||||
if(new_anim->early_apply) {
|
||||
@ -499,6 +501,31 @@ uint32_t lv_anim_resolve_speed(uint32_t speed_or_time, int32_t start, int32_t en
|
||||
return LV_CLAMP(min_time * 10, time, max_time * 10);
|
||||
}
|
||||
|
||||
bool lv_anim_is_paused(lv_anim_t * a)
|
||||
{
|
||||
LV_ASSERT_NULL(a);
|
||||
return a->is_paused;
|
||||
}
|
||||
|
||||
void lv_anim_pause(lv_anim_t * a)
|
||||
{
|
||||
LV_ASSERT_NULL(a);
|
||||
lv_anim_pause_for_internal(a, LV_ANIM_PAUSE_FOREVER);
|
||||
}
|
||||
|
||||
void lv_anim_pause_for(lv_anim_t * a, uint32_t ms)
|
||||
{
|
||||
LV_ASSERT_NULL(a);
|
||||
lv_anim_pause_for_internal(a, ms);
|
||||
}
|
||||
|
||||
void lv_anim_resume(lv_anim_t * a)
|
||||
{
|
||||
LV_ASSERT_NULL(a);
|
||||
a->is_paused = false;
|
||||
a->pause_duration = 0;
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
@ -519,8 +546,20 @@ static void anim_timer(lv_timer_t * param)
|
||||
|
||||
while(a != NULL) {
|
||||
uint32_t elaps = lv_tick_elaps(a->last_timer_run);
|
||||
a->act_time += elaps;
|
||||
|
||||
if(a->is_paused) {
|
||||
const uint32_t time_paused = lv_tick_elaps(a->pause_time);
|
||||
const bool is_pause_over = a->pause_duration != LV_ANIM_PAUSE_FOREVER && time_paused >= a->pause_duration;
|
||||
|
||||
if(is_pause_over) {
|
||||
const uint32_t pause_overrun = time_paused - a->pause_duration;
|
||||
a->is_paused = false;
|
||||
a->act_time += pause_overrun;
|
||||
}
|
||||
}
|
||||
else {
|
||||
a->act_time += elaps;
|
||||
}
|
||||
a->last_timer_run = lv_tick_get();
|
||||
|
||||
/*It can be set by `lv_anim_delete()` typically in `end_cb`. If set then an animation delete
|
||||
@ -529,7 +568,7 @@ static void anim_timer(lv_timer_t * param)
|
||||
*/
|
||||
state.anim_list_changed = false;
|
||||
|
||||
if(a->run_round != state.anim_run_round) {
|
||||
if(!a->is_paused && a->run_round != state.anim_run_round) {
|
||||
a->run_round = state.anim_run_round; /*The list readying might be reset so need to know which anim has run already*/
|
||||
|
||||
/*The animation will run now for the first time. Call `start_cb`*/
|
||||
@ -664,6 +703,14 @@ static int32_t lv_anim_path_cubic_bezier(const lv_anim_t * a, int32_t x1, int32_
|
||||
return new_value;
|
||||
}
|
||||
|
||||
static void lv_anim_pause_for_internal(lv_anim_t * a, uint32_t ms)
|
||||
{
|
||||
|
||||
a->is_paused = true;
|
||||
a->pause_time = lv_tick_get();
|
||||
a->pause_duration = ms;
|
||||
}
|
||||
|
||||
static void resolve_time(lv_anim_t * a)
|
||||
{
|
||||
a->duration = lv_anim_resolve_speed(a->duration, a->start_value, a->end_value);
|
||||
|
@ -25,6 +25,7 @@ extern "C" {
|
||||
|
||||
#define LV_ANIM_REPEAT_INFINITE 0xFFFFFFFF
|
||||
#define LV_ANIM_PLAYTIME_INFINITE 0xFFFFFFFF
|
||||
#define LV_ANIM_PAUSE_FOREVER 0xFFFFFFFF
|
||||
|
||||
/*
|
||||
* Macros used to set cubic-bezier anim parameter.
|
||||
@ -146,6 +147,9 @@ struct _lv_anim_t {
|
||||
|
||||
/* Animation system use these - user shouldn't set */
|
||||
uint32_t last_timer_run;
|
||||
uint32_t pause_time; /**<The time when the animation was paused*/
|
||||
uint32_t pause_duration; /**<The amount of the time the animation must stay paused for*/
|
||||
uint8_t is_paused : 1; /**<Indicates that the animation is paused */
|
||||
uint8_t reverse_play_in_progress : 1; /**< Reverse play is in progress */
|
||||
uint8_t run_round : 1; /**< When not equal to global.anim_state.anim_run_round (which toggles each
|
||||
* time animation timer executes), indicates this animation needs to be updated. */
|
||||
@ -198,6 +202,32 @@ void lv_anim_set_duration(lv_anim_t * a, uint32_t duration);
|
||||
*/
|
||||
void lv_anim_set_delay(lv_anim_t * a, uint32_t delay);
|
||||
|
||||
/**
|
||||
* Resumes a paused animation
|
||||
* @param a pointer to an initialized `lv_anim_t` variable
|
||||
*/
|
||||
void lv_anim_resume(lv_anim_t * a);
|
||||
|
||||
/**
|
||||
* Pauses the animation
|
||||
* @param a pointer to an initialized `lv_anim_t` variable
|
||||
*/
|
||||
void lv_anim_pause(lv_anim_t * a);
|
||||
|
||||
/**
|
||||
* Pauses the animation for ms milliseconds
|
||||
* @param a pointer to an initialized `lv_anim_t` variable
|
||||
* @param ms the pause time in milliseconds
|
||||
*/
|
||||
void lv_anim_pause_for(lv_anim_t * a, uint32_t ms);
|
||||
|
||||
/**
|
||||
* Check if the animation is paused
|
||||
* @param a pointer to an initialized `lv_anim_t` variable
|
||||
* @return true if the animation is paused else false
|
||||
*/
|
||||
bool lv_anim_is_paused(lv_anim_t * a);
|
||||
|
||||
/**
|
||||
* Set the start and end values of an animation
|
||||
* @param a pointer to an initialized `lv_anim_t` variable
|
||||
|
@ -90,5 +90,82 @@ void test_anim_delete_custom(void)
|
||||
lv_test_wait(20);
|
||||
TEST_ASSERT_EQUAL(39, var);
|
||||
}
|
||||
void test_anim_pause(void)
|
||||
{
|
||||
int32_t var;
|
||||
|
||||
/*Start an animation*/
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, &var);
|
||||
lv_anim_set_values(&a, 0, 100);
|
||||
lv_anim_set_exec_cb(&a, exec_cb);
|
||||
lv_anim_set_duration(&a, 100);
|
||||
lv_anim_t * animation = lv_anim_start(&a);
|
||||
|
||||
lv_test_wait(40);
|
||||
TEST_ASSERT_EQUAL(39, var);
|
||||
|
||||
lv_anim_pause(animation);
|
||||
|
||||
lv_test_wait(40);
|
||||
TEST_ASSERT_EQUAL(39, var);
|
||||
|
||||
lv_anim_resume(animation);
|
||||
|
||||
lv_test_wait(20);
|
||||
TEST_ASSERT_EQUAL(59, var);
|
||||
|
||||
lv_test_wait(41);
|
||||
TEST_ASSERT_EQUAL(100, var);
|
||||
}
|
||||
|
||||
void test_anim_pause_for(void)
|
||||
{
|
||||
int32_t var;
|
||||
|
||||
/*Start an animation*/
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, &var);
|
||||
lv_anim_set_values(&a, 0, 100);
|
||||
lv_anim_set_exec_cb(&a, exec_cb);
|
||||
lv_anim_set_duration(&a, 100);
|
||||
lv_anim_t * animation = lv_anim_start(&a);
|
||||
|
||||
lv_anim_pause_for(animation, 20);
|
||||
|
||||
lv_test_wait(40);
|
||||
|
||||
TEST_ASSERT_EQUAL(19, var);
|
||||
|
||||
lv_anim_pause_for(animation, 20);
|
||||
|
||||
lv_test_wait(40);
|
||||
lv_test_wait(40);
|
||||
|
||||
TEST_ASSERT_EQUAL(79, var);
|
||||
}
|
||||
|
||||
void test_anim_pause_for_resume(void)
|
||||
{
|
||||
int32_t var;
|
||||
|
||||
/*Start an animation*/
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, &var);
|
||||
lv_anim_set_values(&a, 0, 100);
|
||||
lv_anim_set_exec_cb(&a, exec_cb);
|
||||
lv_anim_set_duration(&a, 100);
|
||||
lv_anim_t * animation = lv_anim_start(&a);
|
||||
|
||||
lv_anim_pause_for(animation, 40);
|
||||
|
||||
lv_test_wait(20);
|
||||
lv_anim_resume(animation);
|
||||
|
||||
lv_test_wait(20);
|
||||
TEST_ASSERT_EQUAL(19, var);
|
||||
}
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user