一.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; }