Опубликован: 22.12.2015 | Уровень: для всех | Доступ: платный
Лекция 46:

Использование анимации

< Лекция 45 || Лекция 46

Создание анимации

Использование объекта 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);
}

Запустите пример


< Лекция 45 || Лекция 46