Mobile native Wearable native

Elementary Animations: Applying Transition Effects to an Evas Object

This tutorial demonstrates how you can use Elm Transit to create animated transitions effects, such as rotation, wiping, zooming, resizing, and fading, to an Evas_Object.

Warm-up

Become familiar with the Ecore, Elementary, and Evas API basics by learning about:

Setting Up the Application

First create a basic application like explained in the Basic Tutorial.

When the application is ready, create Evas objects and animate them. In this example, one single object is animated with different type of animations.

Create the structure of our application represented by a struct named appdata

typedef struct appdata 
{
   Evas_Object *win;
   Evas_Object *label;
   Evas_Object *button;
   Evas_Object *buttonbck;
   Evas_Object *hbox;
   Evas_Object *left_vbox;
   Evas_Object *center_vbox;
   Evas_Object *right_vbox;
   float rt_angle, zto, zfrom;
} appdata_s;

This structure holds the main UI components of the application:

  • win: the main window
  • label: the title label
  • button: a button object, the target of the animations
  • buttonbck: a button representing the back of the target button
  • left_vbox: a vertical box to place the first buttons column
  • center_vbox: a vertical box to store the second buttons column
  • right_vbox: a vertical box to store the last buttons column
  • hbox: a horizontal box to store the vertical boxes
  • rt_angle, zto, zfrom: these variables are used to store values for animations

Place the UI components on the application's canvas. To make things easier, the UI component creation is split into two functions.

The first function creates UI components on the main window, and the second in the boxes.

create_base_gui(appdata_s *ad)
{
   ad->rt_angle = 360.0;
   ad->zfrom = 1.0;
   ad->zto = 2.0;

   // Window
   ad->win = elm_win_util_standard_add(PACKAGE, PACKAGE);
   elm_win_autodel_set(ad->win, EINA_TRUE);

   if (elm_win_wm_rotation_supported_get(ad->win)) 
   {
      int rots[4] = { 0, 90, 180, 270 };
      elm_win_wm_rotation_available_rotations_set(ad->win, (const int *)(&rots), 4);
   }

   evas_object_smart_callback_add(ad->win, "delete,request", win_delete_request_cb, NULL);

   // Label
   ad->label = elm_label_add(ad->win);
   elm_object_text_set(ad->label, "Effects Tutorial");
   evas_object_size_hint_weight_set(ad->label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   elm_win_resize_object_add(ad->win, ad->label);
   evas_object_show(ad->label);

   // Show the window after the base GUI is set up
   evas_object_show(ad->win);

   ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, keydown_cb, ad);

   // Creation a button in the app window
   ad->button = elm_button_add(ad->win);

   // Moving the button to x=50 y=100
   evas_object_move(ad->button, 50, 100);

   // Resizing the button 100x50
   evas_object_resize(ad->button, 200, 50);

   // Showing the button
   evas_object_show(ad->button);

   // Creation a back button in the app window
   ad->buttonbck = elm_button_add(ad->win);
   elm_object_text_set(ad->buttonbck, "Button back");
   evas_object_move(ad->buttonbck, 50, 100);
   evas_object_resize(ad->buttonbck, 200, 50);

   _create_btn_box(ad);

} // End of create_base_gui

This function takes appdata_s *ad as its only parameter. This function is called by the creation callback app_create of the Tizen application (event_callback.create = app_create;) in the main function of the application.

Set up the needed values like the rotation angle, the original zoom value (zfrom), and the destination zoom value (zto).

ad->rt_angle = 360.0;
ad->zfrom = 1.0;
ad->zto = 2.0;

Create the main window with a title and add the delete callback:

// Window
ad->win = elm_win_util_standard_add(PACKAGE, PACKAGE);
elm_win_autodel_set(ad->win, EINA_TRUE);

if (elm_win_wm_rotation_supported_get(ad->win)) 
{
   int rots[4] = { 0, 90, 180, 270 };
   elm_win_wm_rotation_available_rotations_set(ad->win, (const int *)(&rots), 4);
}

evas_object_smart_callback_add(ad->win, "delete,request", win_delete_request_cb, NULL);

// Label
ad->label = elm_label_add(ad->win);
elm_object_text_set(ad->label, "Effects Tutorial");
evas_object_size_hint_weight_set(ad->label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_win_resize_object_add(ad->win, ad->label);
evas_object_show(ad->label);

// Show the window after the base GUI is set up
evas_object_show(ad->win);

ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, keydown_cb, ad);

Next create the animation target button and the back button. Call the button box creation function with the application data as its parameter.

_create_btn_box(ad);

Add a set of buttons to this box that starts animations on the animation target.

Create the structure of the buttons box with three columns (vertical boxes) and one horizontal for the main container.

// Creation of the main container box
ad->hbox = elm_box_add(ad->win);
elm_box_horizontal_set(ad->hbox, EINA_TRUE);
elm_box_homogeneous_set(ad->hbox, EINA_TRUE);
evas_object_move(ad->hbox, 10, 500);
evas_object_show(ad->hbox);

// Creation of the first column
ad->left_vbox = elm_box_add(ad->hbox);
elm_box_horizontal_set(ad->left_vbox, EINA_FALSE);
elm_box_homogeneous_set(ad->left_vbox, EINA_TRUE);
evas_object_show(ad->left_vbox);
elm_box_pack_start(ad->hbox, ad->left_vbox);

// Creation of the second column
ad->center_vbox = elm_box_add(ad->hbox);
elm_box_horizontal_set(ad->center_vbox, EINA_FALSE);
elm_box_homogeneous_set(ad->center_vbox, EINA_TRUE);
evas_object_show(ad->center_vbox);
elm_box_pack_end(ad->hbox, ad->center_vbox);

// Creation of the last column
ad->right_vbox = elm_box_add(ad->hbox);
elm_box_horizontal_set(ad->right_vbox, EINA_FALSE);
elm_box_homogeneous_set(ad->right_vbox, EINA_TRUE);
evas_object_show(ad->right_vbox);
elm_box_pack_end(ad->hbox, ad->right_vbox);

Then create the first action button for the resize effect.

// Button creation
btn_resize = elm_button_add(ad->win);
// Setting the button text
elm_object_text_set(btn_resize, "Resize");
// Setting the hint weight policy
evas_object_size_hint_weight_set(btn_resize, EVAS_HINT_FILL, EVAS_HINT_FILL);
// Showing the button
evas_object_show(btn_resize);
// Setting the "clicked" callback
evas_object_smart_callback_add(btn_resize, "clicked", _btn_resize_cb, ad);
// Adding the button to the first column
elm_box_pack_end(ad->left_vbox, btn_resize);

evas_object_smart_callback_add defines the callback function that is to be called when the button is clicked. In this example, set a _btn_resize_cb function and pass the application data ad to this callback function.

The callback by itself only sets a new text for the animation target button, and calls a function which will actually animate the button.

static void _btn_resize_cb(void *data, Evas_Object *btn, void *ev)
{
   appdata_s *ad = data;

   // Starting the rotation effect 360 degrees
   // evas_object_resize(ad->button, 100, 50);
   elm_object_text_set(ad->button, "Resize");
   _resize_effect(ad->button);

}

This function is an evas_object_smart_callback and thus needs to have its specific prototype: it does not return anything and receives three parameters:

  • data: data to be passed
  • btn: the object the callback is being called about
  • ev: the actual event, seldom used

In this case, use data to pass the application data to the callback. However, the parameter's type is void * and not appdata_s *. Initialize a variable of the correct type with the pointer.

appdata_s *ad = data;

Then use the application data in the callback function. At this point create the animation directly in the callback function, but it is more straightforward to encapsulate the animation process into a dedicated function. _resize_effect implements the animation code:

static void _resize_effect(Evas_Object *obj)
{
   // Elementary Transition declaration and creation
   Elm_Transit *trans = elm_transit_add();

   // Adding the transition target object
   elm_transit_object_add(trans, obj);

   // Setting the resize effect
   elm_transit_effect_resizing_add(trans, 100, 50, 300, 150);

   // Setting the transition duration
   elm_transit_duration_set(trans, 3.0);

   // Starting the transition
   elm_transit_go(trans);
}

Create an Elm_Transit * object representing the transition.

Elm_Transit *trans = elm_transit_add();

Then add the target object to the transition

elm_transit_object_add(trans, obj);

Add a resizing transition to the object with the origin and destination width and height in pixels.

elm_transit_effect_resizing_add(trans, 100, 50, 300, 150);

100 and 50 are respectively the object's width and height when the effect begins, whereas 300 and 150 are respectively the object's width and height when the effect ends: the object grows from 100×50 to 300×150.

After that set the transition duration with elm_transit_duration_set.

elm_transit_duration_set(trans, 3.0);

The animation lasts three seconds. The duration parameter is a double.

Now start the animation by calling elm_transit_go with the Elm_Transit object.

elm_transit_go(trans);

When the resize button is clicked, the animation target button grows.

All the action buttons are created exactly the same way as the resize button, with a callback and an animation function.

Creating a Rotation Effect

This effect rotates the animation target button with an angle of 360°. This angle is stored in the application data as ad->rt_angle.

Create the button and add it to the center column in the _create_btn_box function.

// The rotation button
btn_rotate = elm_button_add(ad->win);
elm_object_text_set(btn_rotate, "Rotate");
evas_object_size_hint_weight_set(btn_rotate, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(btn_rotate);
evas_object_smart_callback_add(btn_rotate, "clicked", _btn_rotate_cb, ad);
elm_box_pack_end(ad->center_vbox, btn_rotate);

In the rotate button callback, call the effect function with the target button as first parameter and the rotation angle as the second one.

static void _btn_rotate_cb(void *data, Evas_Object *btn, void *ev)
{
   appdata_s *ad = data;

   // Setting the button text
   elm_object_text_set(ad->button, "Rotate");
   _rotation_effect(ad->button, ad->rt_angle);
}

The animation function rotates the animation target by adding a rotation effect with elm_transit_effect_rotation_add. This function takes three parameters:

  • Elm_Transit
  • the rotation position at which the effect begins
  • the rotation position at which the effect ends

Rotation starts at 0° to finish at 360°. The animation lasts two seconds.

static void _rotation_effect(Evas_Object *obj, float angle)
{
   Elm_Transit *trans = elm_transit_add();
   elm_transit_object_add(trans, obj);

   // Rotates the object from its original angle to given degrees to the right
   elm_transit_effect_rotation_add(trans, 0.0, angle);
   elm_transit_duration_set(trans, 2.0);
   elm_transit_go(trans);
}

Creating a Zoom Effect

The zoom effect zooms on the animation target to make it twice bigger. Store the source rate and the destination rate in the application data using ad->zfrom and ad->zto.

Create the button and add it to the center column in the _create_btn_box function.

// The zoom button
btn_zoom = elm_button_add(ad->win);
elm_object_text_set(btn_zoom, "Zoom");
evas_object_size_hint_weight_set(btn_zoom, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(btn_zoom);
evas_object_smart_callback_add(btn_zoom, "clicked", _btn_zoom_cb, ad);
elm_box_pack_end(ad->right_vbox, btn_zoom);

Then add a callback function in order to perform the animation.

static void _btn_zoom_cb(void *data, Evas_Object *btn, void *ev)
{
   appdata_s *ad = data;

   // Starting the rotation effect 360 degrees
   // evas_object_resize(ad->button, 100, 50);
   elm_object_text_set(ad->button, "Zoom");
   _zoom_effect(ad->button, ad->zfrom, ad->zto);
}

To create the zoom effect, use elm_transit_effect_zoom_add with the start rate and the destination rate stored in application data (ad->zfrom and ad->zto)

static void _zoom_effect(Evas_Object *obj, float from, float to)
{
   Elm_Transit *trans = elm_transit_add();
   elm_transit_object_add(trans, obj);

   elm_transit_effect_zoom_add(trans, from, to);
   elm_transit_duration_set(trans, 2.0);
   elm_transit_go(trans);
}

Creating a Flip Effect

This effect is applied to a pair of objects, in the order they are added, to the Elm_Transit transition. In this example, add the animation target button and the button called buttonbck which represents the back of the target button.

Create the action button for the flip effect:

// The flip button
btn_flip = elm_button_add(ad->win);
elm_object_text_set(btn_flip, "Flip x");
evas_object_size_hint_weight_set(btn_flip, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(btn_flip);
evas_object_smart_callback_add(btn_flip, "clicked", _btn_flip_cb, ad);
elm_box_pack_end(ad->left_vbox, btn_flip);

The corresponding callback to create and start the animation with the two objects (target button and back button) to animate is like follows.

static void _btn_flip_cb(void *data, Evas_Object *btn, void *ev)
{
   appdata_s *ad = data;

   // Setting the button text
   elm_object_text_set(ad->button, "Flip");
   _flip_effect(ad->button, ad->buttonbck);
}

Create the function which runs the animation. This flip animation is created using elm_transit_effect_flip_add. The second parameter is the axis of the flip: in this example it is the X axis, so the button flips down to top to show the back button. The last parameter is the flip direction: EINA_TRUE means clockwise.

static void _flip_effect(Evas_Object *obj, Evas_Object *obj2)
{
   Elm_Transit *trans;

   trans = elm_transit_add();
   elm_transit_object_add(trans, obj);
   elm_transit_object_add(trans, obj2);
   elm_transit_effect_flip_add(trans, ELM_TRANSIT_EFFECT_FLIP_AXIS_X, EINA_TRUE);

   elm_transit_duration_set(trans, 3.0);
   elm_transit_go(trans);
}

Creating a Blend Transition

The blend effect also works the same way as the flip, but without the axes or direction information. Use the back button here as well. To create the blend effect button:

// The blend button
btn_blend = elm_button_add(ad->win);
elm_object_text_set(btn_blend, "Blend");
evas_object_size_hint_weight_set(btn_blend, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(btn_blend);
evas_object_smart_callback_add(btn_blend, "clicked", _btn_blend_cb, ad);
elm_box_pack_end(ad->center_vbox, btn_blend);

The blend transition callback is:

static void _btn_blend_cb(void *data, Evas_Object *btn, void *ev)
{
   appdata_s *ad = data;

   // Setting the button text
   elm_object_text_set(ad->button, "Blend");
   _blend_effect(ad->button, ad->buttonbck);
}

Create and start the blend animation. This animation is created by adding it to and Elm_Transit with elm_transit_effect_blend_add. Add two objects, as for the flip.

static void _blend_effect(Evas_Object *obj, Evas_Object *obj2)
{
   Elm_Transit *trans;

   trans = elm_transit_add();
   elm_transit_object_add(trans, obj);
   elm_transit_object_add(trans, obj2);
   elm_transit_effect_blend_add(trans);
   elm_transit_duration_set(trans, 3.0);
   elm_transit_go(trans);
}

Creating a Fade Effect

The fade effect works exactly the same way as the blend effect. First create the button:

// The fade button
btn_fade = elm_button_add(ad->win);
elm_object_text_set(btn_fade, "Fade");
evas_object_size_hint_weight_set(btn_fade, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(btn_fade);
evas_object_smart_callback_add(btn_fade, "clicked", _btn_fade_cb, ad);
elm_box_pack_end(ad->right_vbox, btn_fade);

Then add the button's callback:

static void _btn_fade_cb(void *data, Evas_Object *btn, void *ev)
{
   appdata_s *ad = data;


   // Setting the button text
   elm_object_text_set(ad->button, "Fade");
   _fade_effect(ad->button, ad->buttonbck);
}

The animation function calls elm_transit_effect_fade_add instead of elm_transit_effect_blend_add.

static void _fade_effect(Evas_Object *obj, Evas_Object *obj2)
{
   Elm_Transit *trans;

   trans = elm_transit_add();
   elm_transit_object_add(trans, obj);
   elm_transit_object_add(trans, obj2);
   elm_transit_effect_fade_add(trans);
   elm_transit_duration_set(trans, 3.0);
   elm_transit_go(trans);
}

Creating a Flip on y Axis

This is same as the flip transition, but on y axis. To create a flip on y axis:

// The flip y button
btn_flip_y = elm_button_add(ad->win);
elm_object_text_set(btn_flip_y, "Flip y");
evas_object_size_hint_weight_set(btn_flip_y, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(btn_flip_y);
evas_object_smart_callback_add(btn_flip_y, "clicked", _btn_flip_y_cb, ad);
elm_box_pack_end(ad->left_vbox, btn_flip_y);

static void _btn_flip_y_cb(void *data, Evas_Object *btn, void *ev)
{
   appdata_s *ad = data;


   // Setting the button text
   elm_object_text_set(ad->button, "Flip 2");
   _flip_y_effect(ad->button, ad->buttonbck);
}

static void _flip_y_effect(Evas_Object *obj, Evas_Object *obj2)
{
   Elm_Transit *trans;

   trans = elm_transit_add();
   elm_transit_object_add(trans, obj);
   elm_transit_object_add(trans, obj2);
   elm_transit_effect_flip_add(trans, ELM_TRANSIT_EFFECT_FLIP_AXIS_Y, EINA_TRUE);
   elm_transit_duration_set(trans, 3.0);
   elm_transit_go(trans);
}

Creating a Wipe Effect

The wipe transition is applied on an Evas object considering the wipe type and the direction. Use ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE to hide the button, and ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT to do it from left to right.

The wipe animation button is as follows:

// The wipe button
btn_wipe = elm_button_add(ad->win);
elm_object_text_set(btn_wipe, "Wipe");
evas_object_size_hint_weight_set(btn_wipe, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(btn_wipe);
evas_object_smart_callback_add(btn_wipe, "clicked", _btn_wipe_cb, ad);
elm_box_pack_end(ad->right_vbox, btn_wipe);

The wipe button callback looks like:

static void _btn_wipe_cb(void *data, Evas_Object *btn, void *ev)
{
   appdata_s *ad = data;

   // Starting the rotation effect 360 degrees
   // evas_object_resize(ad->button, 100, 50);
   // Setting the button text
   elm_object_text_set(ad->button, "Wipe");
   _wipe_effect(ad->button);
}

The animation function calls elm_transit_effect_wipe_add with ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE as the second parameter to hide the button and ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT as last parameter to set the direction (left to right).

static void _wipe_effect(Evas_Object *obj)
{
    Elm_Transit *trans;

    trans = elm_transit_add();
    elm_transit_object_add(trans, obj);
    elm_transit_effect_wipe_add(trans, ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE, ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT);
    elm_transit_duration_set(trans, 3.0);
    elm_transit_go(trans);
}
Go to top