Использование анимации
Создание анимации
Использование объекта Animator позволяет осуществлять изменения объектов на экране через определенные промежутки времени. Объект Animator похож на объект Timer, но, в отличие от таймера он позволяет реализовывать различные эффекты. Давайте поговорим об использовании элемента управления GenList в следующем примере.
Создайт новый проект 'AnimatorSample'. Внесите следующие изменения в начале файла исходного кода.
typedef struct appdata { Evas_Object *win; Evas_Object *conform; Evas_Object *label; Evas_Object *rect1; Evas_Object *rect2; } appdata_s; Eina_Bool anim_continue = ECORE_CALLBACK_RENEW; Ecore_Pos_Map pos_map = ECORE_POS_MAP_LINEAR;
Добавьте код в функцию create_base_gui().
/* Conformant */ /*ad->conform = elm_conformant_add(ad->win); elm_win_indicator_mode_set(ad->win, ELM_WIN_INDICATOR_SHOW); elm_win_indicator_opacity_set(ad->win, ELM_WIN_INDICATOR_OPAQUE); evas_object_size_hint_weight_set(ad->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_win_resize_object_add(ad->win, ad->conform); evas_object_show(ad->conform);*/ /* Label*/ /*ad->label = elm_label_add(ad->conform); elm_object_text_set(ad->label, "Hello EFL"); evas_object_size_hint_weight_set(ad->label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_object_content_set(ad->conform, ad->label); evas_object_show(ad->label);*/ /* Evas */ Evas *evas = evas_object_evas_get(ad->win); /* Rect-1 */ ad->rect1 = evas_object_rectangle_add(evas); evas_object_pass_events_set(ad->rect1, EINA_TRUE); evas_object_color_set(ad->rect1, 0, 0, 160, 160); evas_object_resize(ad->rect1, 50, 50); evas_object_show(ad->rect1); /* Animation-1 */ Ecore_Animator *anim = ecore_animator_add(on_next_frame1, ad->rect1); ecore_animator_frametime_set(1. / 60); /* Show window after base gui is set up */ evas_object_show(ad->win);
Добавьте объект Evas для создания объекта Rectangle.
ecore_animator_add(Ecore_Task_Cb, void *) - это API, который создает объект Animator. Временные интервалы задаются в секундах. Добавьте функцию выше create_base_gui() .
static Eina_Bool on_next_frame1(void *data) { static int x = 0; if (x >= 350) x = 0; evas_object_move(data, x += 2, 50); return anim_continue; }
evas_object_move() - это API, который изменяет положение объета на экране.
Запустите пример.
Остановка анимации
Для остановки анимации функция-обработчик события кадра должна возвращать значение ECORE_CALLBACK_CANCEL. Добавьте функцию выше create_base_gui().
static void my_table_pack(Evas_Object *table, Evas_Object *child, int x, int y, int w, int h) { evas_object_size_hint_align_set(child, EVAS_HINT_FILL, 0.5); evas_object_size_hint_weight_set(child, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_table_pack(table, child, x, y, w, h); evas_object_show(child); }
Добавьте код в функцию create_base_gui().
/* Rect-1 */ ad->rect1 = evas_object_rectangle_add(evas); evas_object_pass_events_set(ad->rect1, EINA_TRUE); evas_object_color_set(ad->rect1, 0, 0, 160, 160); evas_object_resize(ad->rect1, 50, 50); evas_object_show(ad->rect1); { /* Box to put the table in so we can bottom-align the table * window will stretch all resize object content to win size */ Evas_Object *box = elm_box_add(ad->win); evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_win_resize_object_add(ad->win, box); evas_object_show(box); /* Table */ Evas_Object *table = elm_table_add(ad->win); /* Make table homogenous - every cell will be the same size */ elm_table_homogeneous_set(table, EINA_TRUE); /* Set padding of 10 pixels multiplied by scale factor of UI */ elm_table_padding_set(table, 20 * elm_config_scale_get(), 10 * elm_config_scale_get()); /* Let the table child allocation area expand within in the box */ evas_object_size_hint_weight_set(table, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); /* Set table to fiill width but align to bottom of box */ evas_object_size_hint_align_set(table, EVAS_HINT_FILL, 1.0); elm_box_pack_end(box, table); evas_object_show(table); { /* Button-1 */ Evas_Object *btn = elm_button_add(ad->win); elm_object_text_set(btn, "■"); evas_object_smart_callback_add(btn, "clicked", btn_stop_cb, NULL); my_table_pack(table, btn, 0, 0, 2, 1); } } evas_object_raise(ad->rect1); /* Animation-1 */ Ecore_Animator *anim = ecore_animator_add(on_next_frame1, ad->rect1);
evas_object_raise() - это API, который перемещает объекты в самый верх экрана. Добавьте обработчик нажатия кнопки выше функции create_base_gui().
static void btn_stop_cb(void *data, Evas_Object *obj, void *event_info) { anim_continue = ECORE_CALLBACK_CANCEL; }
Запустите пример.
Приостановка/возобновление анимации с помощью таймера
Для приостановки анимации, вам нужно использоваться функцией ecore_animator_freeze(). Для возобновления анимации, вам нужно использовать функцию ecore_animator_thaw(). Добавьте новый код в функции create_base_gui (). Этот код создает два таймера.
/* Animation-1 */ Ecore_Animator *anim = ecore_animator_add(on_next_frame1, ad->rect1); /* add 2 timers to go off every 6 seconds */ ecore_timer_add(6, freeze_anim, anim); Ecore_Timer *timer = ecore_timer_add(6, thaw_anim, anim); /* delay the last timer by 3 seconds so the 2 timers are offset */ ecore_timer_delay(timer, 3);
Добавьте две функции выше create_base_gui().
static Eina_Bool freeze_anim(void *data) { ecore_animator_freeze(data); // Animation stop Timer delete return ECORE_CALLBACK_CANCEL; } static Eina_Bool thaw_anim(void *data) { ecore_animator_thaw(data); // Animation restart Timer delete return ECORE_CALLBACK_CANCEL; }
ecore_animator_freeze(Ecore_Animator *) - это API, который приостанавливает анимацию
ecore_animator_thaw(Ecore_Animator *) - это API, который возобновляет.
Запустите пример
Временная шкала анимации
В этом разделе мы поговорим о реализации анимации, воспроизводящейся заданные промежуток времени. Добавьте код в функцию create_base_gui().
/* Rect-1 */ ad->rect1 = evas_object_rectangle_add(evas); evas_object_pass_events_set(ad->rect1, EINA_TRUE); evas_object_color_set(ad->rect1, 0, 0, 160, 160); evas_object_resize(ad->rect1, 50, 50); evas_object_show(ad->rect1); /* Rect-2 */ ad->rect2 = evas_object_rectangle_add(evas); evas_object_pass_events_set(ad->rect2, EINA_TRUE); evas_object_color_set(ad->rect2, 0, 55, 0, 160); evas_object_resize(ad->rect2, 50, 50); evas_object_show(ad->rect2); { ~ } evas_object_raise(ad->rect1); evas_object_raise(ad->rect2); /* Animation-1 */ Ecore_Animator *anim = ecore_animator_add(on_next_frame1, ad->rect1); /* add 2 timers to go off every 6 seconds */ ecore_timer_add(6, freeze_anim, anim); Ecore_Timer *timer = ecore_timer_add(6, thaw_anim, anim); /* delay the last timer by 3 seconds so the 2 timers are offset */ ecore_timer_delay(timer, 3); /* Animation-2 */ ecore_animator_timeline_add(4, on_next_frame2, ad->rect2); /* Show window after base gui is set up */ evas_object_show(ad->win);
ecore_animator_timeline_add(double, Ecore_Timeline_Cb, void *) - это API, который создает объект TimeLine анимации. Добавьте код выше функции create_base_gui().
static Eina_Bool on_next_frame2(void *data, double pos) { double frame = ecore_animator_pos_map(pos, pos_map, 1.2, 15); evas_object_resize(data, 50 * (1 + frame * 2), 50 * (1 + frame * 2)); evas_object_move(data, 200 * frame, 200 * frame + 100); evas_object_color_set(data, 255 * frame, 0, 255 * (1 - frame), 255); return ECORE_CALLBACK_RENEW; }
ecore_animator_pos_map() - это API, который возвращает результирующее значение, которое характеризует текущее состояние анимации. Изменяется от 0 до 1.
Запустите пример.
Добавление ускорения к временной шкале анимации
Добавьте код в функцию create_base_gui().
/* Button-1 */ Evas_Object *btn = elm_button_add(ad->win); elm_object_text_set(btn, "■"); evas_object_smart_callback_add(btn, "clicked", btn_stop_cb, NULL); my_table_pack(table, btn, 0, 0, 2, 1); /* Button-2 */ btn = elm_button_add(ad->win); elm_object_text_set(btn, "Accelerate"); evas_object_smart_callback_add(btn, "clicked", btn_accelerate_cb, ad->rect2); my_table_pack(table, btn, 0, 1, 1, 1); } }
Добавьте обработчик нажатия кнопки выше функции create_base_gui().
static void btn_accelerate_cb(void *data, Evas_Object *obj, void *event_info) { pos_map = ECORE_POS_MAP_ACCELERATE; ecore_animator_timeline_add(4, on_next_frame2, data); }
Запустите пример
Другие стили анимации
Добавьте коды создания кнопок в функцию create_base_gui().
/* Button-2 */ btn = elm_button_add(ad->win); elm_object_text_set(btn, "Accelerate"); evas_object_smart_callback_add(btn, "clicked", btn_accelerate_cb, ad->rect2); my_table_pack(table, btn, 0, 1, 1, 1); /* Button-3 */ btn = elm_button_add(ad->win); elm_object_text_set(btn, "Decelerate"); evas_object_smart_callback_add(btn, "clicked", btn_decelerate_cb, ad->rect2); my_table_pack(table, btn, 1, 1, 1, 1); /* Button-4 */ btn = elm_button_add(ad->win); elm_object_text_set(btn, "Sinusoidal"); evas_object_smart_callback_add(btn, "clicked", btn_sinusoidal_cb, ad->rect2); my_table_pack(table, btn, 0, 2, 1, 1); /* Button-5 */ btn = elm_button_add(ad->win); elm_object_text_set(btn, "Bounce"); evas_object_smart_callback_add(btn, "clicked", btn_bounce_cb, ad->rect2); my_table_pack(table, btn, 1, 2, 1, 1); /* Button-6 */ btn = elm_button_add(ad->win); elm_object_text_set(btn, "Spring"); evas_object_smart_callback_add(btn, "clicked", btn_spring_cb, ad->rect2); my_table_pack(table, btn, 0, 3, 1, 1); } }
Добавьте четыре обработчика нажатия кнопок выше функции create_base_gui().
static void btn_decelerate_cb(void *data, Evas_Object *obj, void *event_info) { pos_map = ECORE_POS_MAP_DECELERATE; ecore_animator_timeline_add(4, on_next_frame2, data); } static void btn_sinusoidal_cb(void *data, Evas_Object *obj, void *event_info) { pos_map = ECORE_POS_MAP_SINUSOIDAL; ecore_animator_timeline_add(4, on_next_frame2, data); } static void btn_bounce_cb(void *data, Evas_Object *obj, void *event_info) { pos_map = ECORE_POS_MAP_BOUNCE; ecore_animator_timeline_add(4, on_next_frame2, data); } static void btn_spring_cb(void *data, Evas_Object *obj, void *event_info) { pos_map = ECORE_POS_MAP_SPRING; ecore_animator_timeline_add(4, on_next_frame2, data); }
Запустите пример
Непрерывные анимации
Добавьте код в функцию create_base_gui().
/* Button-6 */ btn = elm_button_add(ad->win); elm_object_text_set(btn, "Spring"); evas_object_smart_callback_add(btn, "clicked", btn_spring_cb, ad->rect2); my_table_pack(table, btn, 0, 3, 1, 1); /* Button-7 */ btn = elm_button_add(ad->win); elm_object_text_set(btn, "Twice"); evas_object_smart_callback_add(btn, "clicked", btn_twice_cb, ad->rect2); my_table_pack(table, btn, 1, 3, 1, 1); } }
Добавьте обработчики событий выше функции create_base_gui().
static Eina_Bool start_second_anim(void *data) { pos_map = ECORE_POS_MAP_SPRING; ecore_animator_timeline_add(4, on_next_frame2, data); return ECORE_CALLBACK_CANCEL; } static void btn_twice_cb(void *data, Evas_Object *obj, void *event_info) { pos_map = ECORE_POS_MAP_ACCELERATE; ecore_animator_timeline_add(4, on_next_frame2, data); ecore_timer_add(4, start_second_anim, data); }
Запустите пример