一.ClutterAnimation
二.ClutterAnimator:這個類實現的功能比較簡單,而且,最主要是,進行動畫演示後,actor的外觀不會迴歸原來的位置,必須要經過時間軸反轉變回原來的的狀態.
比較喜歡clutter_animator_set函數,可以指定起點,過程關鍵點,以及終點,而且每次都可以按照這個路徑運行效果,對於一些單向重複的過程很有用.
三.下面是一個例子.
#include <stdlib.h>
#include <clutter/clutter.h>
/*actor隊列*/
GQueue *queue;
/*actor結構體*/
typedef struct Item
{
ClutterActor *actor;
ClutterAnimator *move_c2r_animator;
ClutterAnimator *move_c2l_animator;
}Item;
/*定義方向枚舉*/
typedef enum direction
{
right,
left
}direction;
/*定義全局方向亦是,默認從右移入,從左移出*/
direction g_direct = left;
/*定義動畫持續時間*/
#define DURATION 500
/*
* 從中間向右移動畫開始的回調函數
*/
static void
_to_c2r_animation_started_cb (ClutterTimeline *timeline,
gpointer user_data);
/*
* 從中間向左移動畫開始的回調函數
*/
static void
_to_c2l_animation_started_cb (ClutterTimeline *timeline,
gpointer user_data);
/*
* 從中間向右移動畫結束的回調函數
*/
static void
_to_c2r_animation_done_cb (ClutterAnimator *animator,
gpointer user_data);
/*
* 從中間向右移動畫結束的回調函數
*/
static void
_to_c2l_animation_done_cb (ClutterAnimator *animator,
gpointer user_data);
/*
* 設置actor的一些初始信息
* 初始時actor通過把位置設置在stage外使actor不可見.
*/
static void
set_actor_property (ClutterActor *actor)
{
clutter_actor_set_size (CLUTTER_ACTOR (actor), 500, 400);
clutter_actor_set_position (CLUTTER_ACTOR (actor), -500, -400);
clutter_actor_hide (CLUTTER_ACTOR (actor));
}
/*
*將一個從中間向左移動畫和一個從中間向右移動畫與一個actor聯繫起來.
*併爲每個動畫的時間線添加開始和結束的回調函數.
*注意: clutter_animator_set的參數不能將gfloat與int,不然容易出現Segment fault.
*/
static void
bind_animation_to_item (Item *item)
{
gfloat stage_w;
gfloat actor_w;
ClutterTimeline *timeline;
stage_w = clutter_actor_get_width (CLUTTER_ACTOR (clutter_stage_get_default ()));
actor_w = clutter_actor_get_width (item->actor);
item->move_c2r_animator = clutter_animator_new ();
clutter_animator_set_duration (item->move_c2r_animator, DURATION);
clutter_animator_set (item->move_c2r_animator,
item->actor, "x", CLUTTER_EASE_IN_OUT_CUBIC,
0.0, 150.0,
item->actor, "y", CLUTTER_EASE_IN_OUT_CUBIC,
0.0, 200.0,
item->actor, "x", CLUTTER_EASE_IN_OUT_CUBIC,
1.0, stage_w + actor_w,
item->actor, "y", CLUTTER_EASE_IN_OUT_CUBIC,
1.0, 200.0,
item->actor, "scale-x", CLUTTER_EASE_IN_OUT_CUBIC,
0.0, 1.0,
item->actor, "scale-y", CLUTTER_EASE_IN_OUT_CUBIC,
0.0, 1.0,
item->actor, "scale-x", CLUTTER_EASE_IN_OUT_CUBIC,
1.0, 0.1,
item->actor, "scale-y", CLUTTER_EASE_IN_OUT_CUBIC,
1.0, 0.1,
item->actor, "rotation-angle-y", CLUTTER_EASE_IN_OUT_CUBIC,
0.0, 0.0,
item->actor, "rotation-angle-y", CLUTTER_EASE_IN_OUT_CUBIC,
1.0, 180.0,
NULL);
timeline = clutter_animator_get_timeline (item->move_c2r_animator);
g_signal_connect (timeline, "completed",
G_CALLBACK (_to_c2r_animation_done_cb),
item);
g_signal_connect (timeline, "started",
G_CALLBACK (_to_c2r_animation_started_cb),
item);
item->move_c2l_animator = clutter_animator_new ();
clutter_animator_set_duration (item->move_c2l_animator, DURATION);
clutter_animator_set (item->move_c2l_animator,
item->actor, "x", CLUTTER_EASE_IN_OUT_CUBIC,
0.0, 150.0,
item->actor, "y", CLUTTER_EASE_IN_OUT_CUBIC,
0.0, 200.0,
item->actor, "x", CLUTTER_EASE_IN_OUT_CUBIC,
1.0, -actor_w,
item->actor, "y", CLUTTER_EASE_IN_OUT_CUBIC,
1.0, 200.0,
item->actor, "scale-x", CLUTTER_EASE_IN_OUT_CUBIC,
0.0, 1.0,
item->actor, "scale-y", CLUTTER_EASE_IN_OUT_CUBIC,
0.0, 1.0,
item->actor, "scale-x", CLUTTER_EASE_IN_OUT_CUBIC,
1.0, 0.1,
item->actor, "scale-y", CLUTTER_EASE_IN_OUT_CUBIC,
1.0, 0.1,
item->actor, "rotation-angle-y", CLUTTER_EASE_IN_OUT_CUBIC,
0.0, 0.0,
item->actor, "rotation-angle-y", CLUTTER_EASE_IN_OUT_CUBIC,
1.0, 180.0,
NULL);
timeline = clutter_animator_get_timeline (item->move_c2l_animator);
g_signal_connect (timeline, "completed",
G_CALLBACK (_to_c2l_animation_done_cb),
item);
g_signal_connect (timeline, "started",
G_CALLBACK (_to_c2l_animation_started_cb),
item);
}
/*
* 從中間向右移動畫開始的回調函數
*/
static void
_to_c2r_animation_started_cb (ClutterTimeline *timeline,
gpointer user_data)
{
Item *item = (Item *)user_data;
if (item == NULL)
return;
clutter_actor_show (item->actor);
}
/*
* 從中間向左移動畫開始的回調函數
*/
static void
_to_c2l_animation_started_cb (ClutterTimeline *timeline,
gpointer user_data)
{
Item *item = (Item *)user_data;
if (item == NULL)
return;
clutter_actor_show (item->actor);
}
/*
* 從中間向右移動畫結束的回調函數
*/
static void
_to_c2r_animation_done_cb (ClutterAnimator *animator,
gpointer user_data)
{
Item *item = (Item *)user_data;
g_assert (item!= NULL);
if (g_direct == right)
g_queue_push_tail (queue, item);
}
/*
* 從中間向右移動畫結束的回調函數
*/
static void
_to_c2l_animation_done_cb (ClutterAnimator *animator,
gpointer user_data)
{
Item *item = (Item *)user_data;
g_return_if_fail (item != NULL);
if (g_direct == left)
g_queue_push_tail (queue, item);
}
/*
*將當前居中原比例顯示的一項item調至最底部,也即是從當前畫面移除
*變成等待隊列的最後一項
*注意: 如果移動方向是從左向右:
*即當前item的從中間移動到右邊的動畫有效,且:
* 此item的從中間到右的item動畫正向
*否則, 當前item的從中間移到左邊的動畫有效,且:
* 此item的從中間到左的item動畫正向
*
*/
raise_item_to_bottom (Item *item)
{
ClutterTimeline *timeline;
if (item == NULL)
return;
if (g_direct == left)
{
timeline = clutter_animator_get_timeline (
item->move_c2l_animator);
clutter_timeline_set_direction (timeline,CLUTTER_TIMELINE_FORWARD);
clutter_animator_start (item->move_c2l_animator);
}
else
{
timeline = clutter_animator_get_timeline (
item->move_c2r_animator);
clutter_timeline_set_direction (timeline, CLUTTER_TIMELINE_FORWARD);
clutter_animator_start (item->move_c2r_animator);
}
}
/*
*將等待顯示的第一項item調至最頂部,也即是移到到顯示居中位置
*注意: 如果移動方向是從左向右:
*即當前item的從中間移動到左邊的動畫有效,且:
* 此item的從中間到左的item動畫反向
*否則, 當前item的從中間移到右邊的動畫有效,且:
* 此item的從中間到右的item動畫反向
*/
static void
raise_item_to_top (Item *item)
{
ClutterTimeline *timeline;
if (item == NULL)
return;
if (g_direct == left)
{
timeline = clutter_animator_get_timeline (
item->move_c2r_animator);
clutter_timeline_set_direction (timeline, CLUTTER_TIMELINE_BACKWARD);
clutter_animator_start (item->move_c2r_animator);
}
else
{
timeline = clutter_animator_get_timeline (
item->move_c2l_animator);
clutter_timeline_set_direction (timeline, CLUTTER_TIMELINE_BACKWARD);
clutter_animator_start (item->move_c2l_animator);
}
}
/*
*處理鍵盤事件.
*如果當然有有動畫正在播放,則忽略鍵盤事件
*如要是向左方向鍵,說明actor從右邊移入,從左邊移出
*如果是向右方向鍵,說明actor從左邊移入,從右邊移出
*/
static gboolean
_on_stage_key_cb (ClutterActor *actor,
ClutterEvent *event,
gpointer user_data)
{
static Item *curr_item = NULL;
GQueue *queue = (GQueue *)user_data;
if (curr_item != NULL)
{
if (clutter_timeline_is_playing (clutter_animator_get_timeline
(curr_item->move_c2r_animator)))
return;
if (clutter_timeline_is_playing (clutter_animator_get_timeline
(curr_item->move_c2l_animator)))
return;
}
guint keyval = clutter_event_get_key_symbol (event);
switch (keyval)
{
case CLUTTER_Left:
g_direct = left;
break;
case CLUTTER_Right:
g_direct = right;
break;
default:
return;
}
raise_item_to_bottom (curr_item);
curr_item = g_queue_pop_head (queue);
raise_item_to_top (curr_item);
}
/*
* main函數.
* 缺少一些資源釋放
* 編譯命令: gcc *.c -o main `pkg-config --cflags --libs --clutter-1.0`
* */
int main (int argc, char *argv[])
{
gfloat x, y;
ClutterActor *stage;
ClutterColor stage_color = {0x00, 0x00, 0x00, 0xff};
ClutterColor rect_color = {0xff, 0x00, 0x00, 0xff};
queue = g_queue_new ();
clutter_init (&argc, &argv);
stage = clutter_stage_get_default ();
clutter_stage_set_title (CLUTTER_STAGE (stage), "Hello");
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
clutter_actor_set_size (stage, 800, 800);
int i;
for (i = 0; i < 5; i++)
{
Item *item = (Item *)malloc (sizeof (Item));
item->actor = clutter_rectangle_new_with_color (&rect_color);
set_actor_property (CLUTTER_ACTOR (item->actor));
clutter_container_add_actor (CLUTTER_CONTAINER (stage), CLUTTER_ACTOR (item->actor));
bind_animation_to_item (item);
g_queue_push_tail (queue, item);
}
/*添加鍵盤事件*/
g_signal_connect (stage, "key-press-event", G_CALLBACK (_on_stage_key_cb), queue);
clutter_actor_show (stage);
clutter_main ();
return EXIT_SUCCESS;
}