当前位置: BOLT界面引擎 > 知识库文章 > HelloBolt系列教程 > HelloBolt5:使用动画

HelloBolt5:使用动画

作者:Tsukasa

     在HellohBolt5中,我们将在HelloBolt4的基础上加入两个很Cool的动画效果,让界面动起来:第一,在关机图标上,每隔5s将其变为另一个图标;第二,当点击关闭按钮时,星星图标在原位置上逐渐变大并消失,正中的HelloBolt文本向右“飞出”界面,之后程序退出。

   
   
  前面的教程中已经说过,Bolt在一个内置时钟的驱动下,每隔若干时间对对象树进行一次渲染,更新对象树上被改变部分的输出,并将渲染结果在容器窗口中显示,称为一帧。比如在前一帧渲染之后,将某个对象移动位置,那么在下一帧渲染时,Bolt会重新渲染对象树上该对象之前的位置部分和之后的位置部分,这样展示出来的界面就发生了变化。如果我们将改变某对象位置这个操作的时间延长,比如延长到100帧,指定对象的初始位置和结束位置,并按照一定的规则对中间每一帧的对象位置进行插值,那么在每一帧中,对象只会被移动一小段距离,渲染出来的结果也会发生相应微小的改变,这样在这段时间内的,视觉上,界面就会展示出对象从初始位置连续移动到结束位置的效果,这就是Bolt中关键帧动画的原理。我们称动画执行的这段时间为持续时间,动画中每一帧的时刻为运行时刻,依照动画改变属性的对象为动画的执行对象。
首先,让我们来看看退出程序时的动画是如何实现的。转到MainWnd.xml.lua中在close_btn_OnLButtonDown函数定义代码如下:
local aniFactory = XLGetObject("Xunlei.UIEngine.AnimationFactory")
     local alphaAni = aniFactory:CreateAnimation("AlphaChangeAnimation")
以上两行中,"Xunlei.UIEngine.AnimationFactory"标识的全局对象是Bolt用于创建动画对象的动画工厂对象, 在动画工厂对象上调用CreateAnimation接口创建指定类型的动画对象,可以创建的动画类型包括Bolt的内建动画(包括改变对象透明度的AlphaChangeAnimation,改变对象位置的PosChangeAnimation等)及在布局xml中自定义的动画类型。这里创建的是一个类型为AlphaChangeAnimation动画对象。

alphaAni:SetTotalTime(700)

alphaAni:SetKeyFrameAlpha(255,0)
以上两行,设置刚创建出来的动画对象的几个关键属性。SetTotalTime接口以ms为单位,指定动画的持续时间,对于改变对象透明度(alpha)的动画来说,要指定执行对象的初始和结束的透明度,通过调用SetKeyFrameAlpha接口来设置。这样这个动画就可以在700ms内将执行对象的透明度从全不透明(255)改变到全透明(0).

local owner = self:GetOwner()

         local icon = owner:GetUIObject("icon")
以上两行获取指向星星图标对象的引用。因为close_btn_OnLButtonDown的self参数指向的是关闭按钮逻辑对象,而星星图标对象与之在同一对象树之上,可以通过对象树的对象索引接口得到该对象,调用UIObject的GetOwner接口返回该对象所在的对象树对象,调用对象树的GetUIObject接口获取对象树上指定id的UIObject对象,这样我们就得到了需要的对象;

alphaAni:BindRenderObj(icon)

          owner:AddAnimation(alphaAni)
         alphaAni:Resume()

以上几行,用动画的BindRenderObj接口指定执行对象,调用AddAnimation接口将动画对象加入到对象树的正在运行动画列表中,只有加入到该列表中的动画对象才能在时钟的驱动下,更新动画的运行时刻,当到达持续时间时,该动画结束,同时被从列表中移除。最后调用Resume接口,指定动画开始执行。
        类似的创建并执行另外几个动画,注意这里有两个不同动画对象指定了同一个执行对象,在Bolt里这是允许的,前提是两个动画对象是作用于对象的不同属性之上的,比如这里一个动画对象改变透明度,另一个改变位置,如果两个动画对象都改变透明度,Bolt会按照一定的规则来解决两个动画对象的冲突。
     动画的引入让我们的交互逻辑产生了变化:不能在close_btn_OnLButtonDown事件中立刻退出应用程序了,要让HelloBolt在动画结束之后再退出。为了达到这个目的,我们需要为动画对象添加状态改变的响应函数, 动画状态改变响应函数的原型为function onStateChange(self,oldState,newState), self是指向状态改变的动画对象的引用,oldState 和 newState表示改变时的前状态和后状态, 动画的状态 是从0 到 4的整形, 当为4时标明动画已经执行完成,退出程序,代码如下所示:

if newState == 4 then

              os.exit()
     end

     之后调用动画对象上的AttachListener接口指定上面定义的函数作为动画对象的状态响应函数,代码如下:

posAni2:AttachListener(true,onAniFinish)

这样当posAni2动画对象执行完成时,程序退出。
 
     上面使用了Bolt的内建动画,已经可以满足大部分常用动画需求(内建动画手册),除此之外,Bolt还提供了自定义动画机制(自定义动画指南)。转到MainWnd.xml中,定义一个自定义动画,xml节点如下所示:
<animation_def class="HelloBolt.ani">
定义自定义动画要在布局xml中加入<animation_def>节点,其中class属性指定动画的类型名;在<method_def>子节点中加入<Action>节点定义动画的行为, Action函数的原型为function Action(self), 当对象树在每帧中渲染的时候,都会调用该函数。在method_def节点中定义函数, 类似于在eventlist中定义event。比如<Action file=xxx func=yyy/>,其中节点名指定函数名, 该函数名可以作为对象的方法直接调用, 比如HelloBolt.ani类型的对象a可以在lua中用a:Action()的方式调用Action。我们在这里使用Bolt中另一种定义方法或事件的方式: 直接在布局xml中定义方法, 格式如<Action>函数体</Action> 和 <event name=OnLButtonDown>函数体</event>,这种写法比较适合教学演示实例代码,不推荐在实际的工程开发中使用。Action函数的定义如下:

local attr = self:GetAttribute()

     local obj = attr.obj  
local runningTime = self:GetRuningTime()
以上三行中,调用GetRunningTime() 和 GetTotalTime()接口分别获取动画对象执行时刻和通过SetTotalTime()设置的持续时间, 通过这两个值可以自行计算自定义动画的进度。在自定义对象(自定义动画对象和自定义控件对象)上调用GetAttribute()方法获取绑定到该对象上的一个lua table实例,称为属性表。可以在属性表上之上加入任何lua 对象, 在自定义对象的生命周期里可以访问属性表。 虽然没有为自定义动画定义类似BindObject的方法, 但是自定义动画仍然可以在执行Action时通过属性表获取执行对象。在这个Action的定义中,每隔5000ms将执行对象展示的位图改变。

        定义好了自定义动画之后,要通过跟使用内置动画类似的流程来使用之,代码如下所示:

local aniFactory = XLGetObject("Xunlei.UIEngine.AnimationFactory")

     myAni = aniFactory:CreateAnimation("HelloBolt.ani")
     myAni:SetTotalTime(9999999)
     local aniAttr = myAni:GetAttribute()
     aniAttr.obj = newIcon
     owner:AddAnimation(myAni)
     myAni:Resume()

与创建Bolt内置动画基本相同,只是在调用CreateAnimation接口时传入自定义动画的类型名。对照自定义动画Action的定义,通过调用GetAttribute()接口获取属性表并在其中加入元素,将执行对象传入到Action定义中使用。

    

迅雷公司 版权所有 Copyright 2003-2010 Thunder Inc.All Rights Reserved. 意见反馈:xl7doc@xunlei.com