# 5. 动画

本章导读:

一个炫酷的GUI界面是离不开动画的,通过使用动画给人用户眼前一亮的感觉。AWTK提供了多种动画机制,可以让GUI变得更加的形象、流畅。

# 5.1 简介

AWTK提供了两大类动画:窗口动画和控件动画,下面介绍如何使用这两种动画。

# 5.2 窗口动画

窗口动画是现代GUI最基本的功能之一,在窗口打开或关闭时,引入一个过渡动画,让用户感觉这个过程是流畅的。窗口动画的基本原理很简单:在打开或关闭窗口时,把前后两个窗口预先绘制到两张内存图片上,按照指定规则显示两张图片,形成动画效果。

# 5.2.1 动画类型

窗口本身只需指定期望的动画类型,由窗口管理器负责在适当的时候(如打开和关闭窗口时),创建窗口动画并让窗口动画绘制到屏幕上。在窗口动画期间,窗口管理器会禁止窗口本身的绘制,并忽略所有输入事件。目前支持的动画有:普通窗口动画和对话框动画。

  • 普通窗口动画详见下表:
窗口动画类型 说明
htranslate 左右平移动画(速度最快,嵌入式平台推荐使用)
vtranslate 上下平移动画
slide_up 向上弹出
slide_down 向下弹出
slide_left 向左弹出
slide_right 向右弹出
  • 对话框动画详见下表:
窗口动画类型 说明
popup 向上弹出(速度最快,嵌入式平台推荐使用)
popdown 向下弹出
fade 淡入淡出动画
center_scale 缩放动画(没有硬件时加速慎用)

以前的bottom_to_top相当于popup,仍然可以使用,但建议用popup代替。以前的top_to_bottom相当于popdown,仍然可以使用,但建议用popdown代替。

# 5.2.2 使用方法

给窗口或对话框指定动画效果,只需设置窗口或对话框的anim_hint属性即可,代码如下:

<window name="main" anim_hint="vtranslate">
...
</window>

# 5.2.3 动画参数

可以为动画指定参数,其格式为类似函数调用的参数格式。

(1)所有动画都支持下面的参数:

  • duration 动画持续时间(毫秒)
  • easing 插值算法名称

如:

anim_hint="center_scale(duration=300)"

(2)slide_up、slide_down、slide_left和slide_right动画特有参数:

  • start_alpha 起始alpha值(0-255)
  • end_alpha 结束alpha值(0-255)
  • alpha 相当于将start_alpha和end_alpha设置为同一个值

alpha值用于在背景上画一层透明的颜色,这能够实现让背景变暗的效果。如果start_alpha和end_alpha不相同,则能实现动态变暗的效果,这有额外的运行开销,如果性能不佳,建议设置alpha即可。

# 5.2.4 示例

给窗口或对话框指定动画效果,只需设置窗口或对话框的anim_hint属性即可,下面以awtk/bin/demoui.exe中的主界面main.xml为例,代码如下:

<!-- awtk/demos/assets/default/raw/ui/main.xml -->
<window closable="no" text="Desktop" anim_hint="htranslate">
  <slide_view x="0" y="0" w="100%" h="100%">
    <view x="0" y="0" w="100%" h="100%" children_layout="default(c=2,r=8,m=5,s=5)">
      <button name="open:basic" text="Basic"/>
      <button name="open:button" text="Buttons"/>
      <button name="open:edit" text="Edits"/>
      <button name="open:keyboard" text="KeyBoard"/>
      <button name="open:list_view" text="ListView"/>
      <button name="open:slide_view" text="SlideView"/>
      <button name="open:animation" text="Animate Window"/>
      <button name="open:animator" text="Animate Widget"/>
      <button name="open:tab_control" text="Tab Control"/>
      <button name="open:combo_box" text="ComboBox"/>
      <button name="open:rich_text" text="RichText"/>
      <button name="open:color_picker" text="Color Picker"/>
    </view>
    ...
</window>	

还可以指定动画时长(duration,单位为毫秒),格式与函数调用类似,不过参数用name=value的形式,如:

anim_hint="center_scale(duration=300)"

# 5.2.5 自定义动画

开发者可以自定义动画,自定义的动画可以像内置动画一样,在XML文件中启用。

自定义动画非常简单,通常只需要几行代码即可。步骤如下:

(1)实现window_animator_t接口。如:

static const window_animator_vtable_t s_window_animator_popup_vt = {
.overlap = TRUE,
.type = "popup",
.desc = "popup",
.size = sizeof(window_animator_t),
.draw_prev_window = window_animator_overlap_default_draw_prev,
.draw_curr_window = window_animator_to_top_draw_curr};
window_animator_t* window_animator_popup_create(bool_t open, object_t* args) {
return window_animator_create(open, &s_window_animator_popup_vt);
}

(2)注册到window_animator工厂。如:

window_animator_factory_register(factory, WINDOW_ANIMATOR_POPUP, window_animator_popup_create);

# 5.3 控件动画

控件动画是一种很常见的动画,常用于入场动画、离场动画、装饰用户界面和吸引用户注意力等。

# 5.3.1 动画类型

AWTK目前支持的控件动画类型详见下表:

控件动画类型 说明
move 通过改变控件位置形成动画效果
value 通过改变控件值形成动画效果
opacity 通过改变控件透明度形成动画效果
scale 通过改变控件缩放比例形成动画效果(目前需要vgcanvas)
rotation 通过改变控件旋转角度形成动画效果(目前需要vgcanvas,draw_type为icon才能旋转)
其它任何数值型的属性 如x/y/w/h等等

# 5.3.2 特色

  • 支持逆向模式
  • 支持停止和暂停
  • 支持定时(延迟)执行
  • 支持重复模式(可指定次数)
  • 支持往返模式(可指定次数)
  • 支持多种插值算法(如加速和减速等)
  • 支持同一控件多个动画并行执行
  • 支持同一控件多个动画串行执行
  • 支持时间倍率,让时间变快和变慢
  • 支持按名称去开始、暂停、停止和销毁动画

# 5.3.3 函数

AWTK提供了的函数接口详见下表,具体请查看AWTK_API手册。

函数名称 说明
widget_animator_destroy 销毁animator对象
widget_animator_init 初始化仅供子类内部使用
widget_animator_off 注销指定事件的处理函数
widget_animator_on 注册指定事件的处理函数
widget_animator_pause 暂停动画
widget_animator_set_destroy_when_done 设置完成时是否自动销毁动画对象(缺省销毁)
widget_animator_set_name 设置名称
widget_animator_set_repeat 设置为重复模式
widget_animator_set_reversed 设置为逆向模式
widget_animator_set_time_scale 设置时间倍率,用于实现时间加速减速和停滞的功能
widget_animator_set_yoyo 设置为yoyo模式
widget_animator_start 启动动画
widget_animator_stop 停止动画

# 5.3.4 XML参数

1、公共参数,详见下表:

参数 说明
name 动画名称(缺省为动画的类型如move)
delay 延迟启动时间(毫秒)
duration 时长(毫秒)
easing 插值算法(见后面描述)
yoyo_times 往返的次数(x2),为0视为永久播放
repeat_times 重复的次数,为0视为永久播放
auto_start 创建后自动启动(缺省为true)
auto_destroy 完成后自动销毁(缺省为true)

2、widget_animator_move动画的参数,详见下表:

参数 说明
x_from x起始位置
y_from y起始位置
x_to x结束位置
y_to y结束位置

3、widget_animator_value动画的参数,详见下表:

参数 说明
from 起始值
to 结束值

4、widget_animator_opacity动画的参数,详见下表:

参数 说明
from 起始值(0-255)
to 结束值(0-255)

5、widget_animator_scale动画的参数,详见下表:

参数 说明
x_from x方向缩放起始值
y_from y方向缩放起始值
x_to x方向缩放结束值
y_to y方向缩放结束值

6、widget_animator_rotation动画的参数,详见下表:

参数 说明
from 起始值(弧度)
to 结束值(弧度)

7、其它数值型属性动画的参数,详见下表:

参数 说明
from 起始值
to 结束值

# 5.3.5 插值算法名称(easing)

easing的类型和可取的值如下:

  1. linear:

    • linear
  2. quadratic:

    • quadratic_out
    • quadratic_inout
  3. cubic:

    • cubic_in
    • cubic_out
  4. sin:

    • sin_in
    • sin_out
    • sin_inout
  5. pow:

    • pow_in
    • pow_out
    • pow_inout
  6. circular:

    • circular_in
    • circular_out
    • circular_inout
  7. elastic:

    • elastic_in
    • elastic_out
    • elastic_inout
  8. back:

    • back_in
    • back_out
    • back_inout
  9. bounce

    • bounce_inout
    • bounce_out
    • bounce_inout

# 5.3.6 示例

既可以在UI文件的XML中,也可以使用C代码中创建动画,接下来将分别介绍如何在XML和C代码中创建动画。

1. 在XML中

在缺省情况下,动画创建后自动启动,完成后自动销毁。可以指定auto_start=false禁止创建后自动启动,指定参数auto_destroy=false禁止完成时自动销毁(控件销毁时仍然会自动销毁)。

在XML中可以使用animation参数创建动画,多个参数可以用";"分隔,此方法最为简单,后续可以在程序中通过动画名字,对动画进行启动和暂停等控制。下面以awtk/bin、demoui.exe中的AnimateWidget页面为例,代码如下:

<!-- awtk/demos/assets/default/raw/ui/animator.xml -->
<window>
  <image name="fade" image="logo" x="center" y="10" w="200" h="60" opacity="0" 
    animation="opacity(from=50, to=255, yoyo_times=1000, duration=1000)" />
  <image name="fade" image="logo" x="center" y="80" w="200" h="60" opacity="0" 
    animation="opacity(from=50, to=255, yoyo_times=1000, duration=1000, delay=1000)" />
  <image name="fade" image="logo" x="center" y="150" w="200" h="60" opacity="0" 
    animation="opacity(from=50, to=255, yoyo_times=1000, duration=1000, delay=2000)" />
  <image name="move" image="logo" x="0" y="middle:60" w="200" h="60" 
    animation="move(x_from=0, x_to=200, yoyo_times=1000, duration=1000, delay=3000)"/>
  <progress_bar name="value" x="center" y="middle" w="90%" h="40" 
    animation="value(from=50, to=100, yoyo_times=1000, duration=1000, delay=4000)"/>
  <button name="close" x="center" y="bottom:10" w="25%" h="30" text="Close"/>
</window>

2. 在C代码中

在C代码中有两种方式创建动画,下面以awtk/bin/demo_animator.exe为例:

(1)采用widget_animator_xxx_create,其中xxx可取值move/value/opacity/scale/rotation,此方法比较麻烦,不再推荐使用,代码如下:

/* awtk/demos/demo_animator_app.c */
ret_t application_init() {
  ...
  animator = widget_animator_move_create(image, 1000, delay, EASING_SIN_INOUT);
  widget_animator_move_set_params(animator, image->x, image->y, image->x + 100, image->y + 100);
  widget_animator_set_destroy_when_done(animator, FALSE);
  widget_animator_set_repeat(animator, times);
  widget_animator_start(animator);
  ...
}

(2)通过函数widget_create_animator创建动画,推荐使用,代码如下:

/* awtk/demos/demo_animator_app.c */
ret_t application_init() {
  ...
  widget_create_animator(progress_bar, "value(from=50, to=100, duration=500, yoyo_times=1000, delay=1000)");
  widget_create_animator(opacity, "opacity(to=50, duration=500, yoyo_times=1000)");
  widget_create_animator(image6, "opacity(to=50, duration=500, yoyo_times=1000, delay=1000)");
  widget_create_animator(image2, "rotation(to=6.28, yoyo_times=0, duration=1000, easing=sin_out)");
  widget_create_animator(image3, "scale(x_to=-1, yoyo_times=1000, duration=1000, easing=sin_out)");
  widget_create_animator(image4, "scale(x_to=2, y_to=2, yoyo_times=1000, duration=1000, easing=sin_out)");
  widget_create_animator(image5, "y(to=400, duration=1000, easing=sin_out)");
  widget_create_animator(image5, "opacity(to=0, duration=500, yoyo_times=1000, delay=1000)");
  ...
}