DirectUI通用动画框架

在编写VC界面时,编写动画比较困难,代码重用性不高。编写一个临时动画需要创建定时器或者线程来驱动改变渲染状态,来达到画面实时改变的目的。但是定时器和线程都是比较难以维护的,处理不好很容易造成资源浪费甚至程序崩溃。

Skilla在上一周整理好了skillcore库,这一次又给它增添了通用动画框架。这个动画框架本身没有渲染功能,主要是提供动画的驱动事件,使用时需要自己去处理动画事件去完成动画渲染。该框架比较简单,动画由线程来驱动,下面展示一下具体的构成。

根据动画的特点,就像播放动画片一样,Skilla把动画抽象成了一个动画基类BaseAnimation,里面包括动画的运行时间,运行状态,循环状态,正反序等等。使用时可以调用PlayAnimation,PauseAnimation,ResumeAnimation,StopAnimation等方法来控制动画的运行状态。动画本身还可以绑定动画监听器AnimationListener来触发动画状态改变时的事件,以方便处理。BaseAnimation本身是个抽象类,使用时需实现virtual bool
FirstRun() = 0; virtual void Run() = 0; virtual bool LastRun() = 0;这三个接口,firstRun触发时,渲染动画的初始状态,lastRun触发时渲染动画的结束状态,Run触发时则根据runningTime这个时间轴属性来渲染动画每一帧的状态。为了方便使用Skilla实现了三个常用动画子类,PosChangeAnimation  AlphaChangeAnimation和SeqFrameAnimation,它们分别是位置改变动画,渐隐渐显(透明度改变)动画以及序列帧动画。关于使用方法在下面介绍。

由于动画的生命周期难以管理,因为有的动画为临时动画,播放一次就再也不用了;而有的动画则需要重复使用,甚至绑定到控件上,和执行动画的控件同生共死。之所以出现这个问题就是因为把动画抽象成了类。这时候用指针来管理动画的生命周期明显是个坏主意,为了保证其通用性,我们采用动画工厂来管理动画的生命周期,创建动画时采用AnimationFactory动画工厂,操作现有动画时,使用AnimationFactory的FindAniamtion方法通过aniamtionName取到动画对象指针,删除动画同样要使用AnimationFactory通过animationName来删除。在应用程序退出时,需要AnimationFactory清理掉所有的剩余动画对象。

下面以duilib界面库为例,看看具体如何使用的

class CloseAnimationListener : public AnimationListener
{
public:
	LRESULT OnStop(std::int64_t runningTime,std::int64_t totalTime,bool bReverse,bool bLoop)
	{
		AnimationFactory::GetInstance()->DeleteAnimation(L"PosChange.CloseAni");
		DuiApplicationBase::GetInstance()->RequestQuit();
		return AnimationListener::OnStop(runningTime,totalTime,bReverse,bLoop);
	}

};

class AlphaChangeListener : public AnimationListener
{
public:
	LRESULT OnPlayEnd(std::int64_t runningTime,std::int64_t totalTime,bool bReverse,bool bLoop)
	{
		BaseAnimation* p = AnimationFactory::GetInstance()->FindAnimation(L"AlphaChange.InitAni");
		p->SetReverse(!p->GetReverse());
		return 0;
	}
};

class CMainFrame
 : public WindowImplBase ,public IPosChangeAnimation,public ISeqFrameAnimation,public IAlphaChangeAnimation
{
public:
	CMainFrame(void);
	~CMainFrame(void);

	//duilib相关
	static CMainFrame* Instance();
	virtual CDuiString     GetSkinFolder();
	virtual CDuiString     GetSkinFile();
	virtual LPCTSTR       GetWindowClassName(void) const;
	CControlUI*            CreateControl(LPCTSTR pstrClass);

	virtual void SetAnimationPos(const RECT& rect)   //实现位置改变动画接口
	{
		CDuiRect r(rect);
		::MoveWindow(*this,r.left,r.top,r.right-r.left,r.bottom-r.top,false);
	}

	virtual void SetAnimationAlpha(const int Alpha)
	{
		CControlUI* pContrl = m_PaintManager.FindControl(L"alphaChange");
		String str;
		str.Format(L"file='alpha.png' fade='%d'",Alpha);
		pContrl->SetBkImage(str);
	}

	virtual void SetAnimationSeqFrame(const int framePos)   //实现序列帧动画接口
	{
		CControlUI* pControl = m_PaintManager.FindControl(L"bg");
		if (framePos==0)
		{
			pControl->SetBkImage(L"11.jpg");
		}else if (framePos==1)
		{
			pControl->SetBkImage(L"12.jpg");
		}else if (framePos==2)
		{
			pControl->SetBkImage(L"13.jpg");
		}else if (framePos==3)
		{
			pControl->SetBkImage(L"7.jpg");
		}
	}
	//窗口相关
	void InitWindow();
	LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
	LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
	LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
	void Notify(TNotifyUI& msg);

	ScopedPtr<Thread> initThread;
	ScopedPtr<Thread> destroyThread;
	ScopedPtr<CloseAnimationListener>  closeListener;
	ScopedPtr<AlphaChangeListener>   alphaListener;
};

首先,将被动画操作的控件事件对应的动画接口,这里以CMainFrame为动画控件,为了方便同时展现三种动画,直接给它把三个动画接口全部实现了,实现具体的动画渲染操作,另外还定义了两个动画监听器的子类CloseAnimationListener,AlphaChangeListener,用来监听动画的运行状态。

下面是实现部分

void CMainFrame::Notify(TNotifyUI& msg)
{
	if (_tcsicmp(msg.sType,_T("windowinit"))==0)
	{
		  closeListener = new CloseAnimationListener;
		  alphaListener = new AlphaChangeListener;
		  //创建一个序列帧动画
		  SeqFrameAnimation* animation = ( SeqFrameAnimation*)AnimationFactory::GetInstance()->CreateAnimation(L"SeqFrame.InitAni",SEQ_FRAME_ANIMATION);
		  animation->SetIntervalTime(600);   //设置时间间隔
		  animation->SetFrameSize(4);       //设置帧数
		  animation->BindObject(this);      //绑定对象
		  animation->SetLoop(true);         //设置循环
		  animation->PlayAnimation();       //开始播放

		  //创建一个渐隐渐显动画
		  AlphaChangeAnimation* animation2 = ( AlphaChangeAnimation*)AnimationFactory::GetInstance()->CreateAnimation(L"AlphaChange.InitAni",ALPHA_CHANGE_ANIMATION);
          animation2->RegistListener(alphaListener);
		  animation2->SetTotalTime(3000);
		  animation2->SetKeyFrameRect(0,255);
		  animation2->BindObject(this);      //绑定对象
		  animation2->SetLoop(true);         //设置循环
		  animation2->PlayAnimation();       //开始播放

	}else if (_tcsicmp(msg.sType,_T("click")) == 0)
	{
		if (_tcsicmp(msg.pSender->GetName(),_T("btn_close")) == 0)
		{
			PosChangeAnimation*  animation = (PosChangeAnimation*)AnimationFactory::GetInstance()->CreateAnimation(L"PosChange.CloseAni",POS_CHANGE_ANIMATION);
			animation->SetTotalTime(600);                       //设置时间
			RECT rect;
			GetWindowRect(*this,&rect);
			RECT rectTo = {rect.left,(rect.top+rect.bottom)/2,rect.right,(rect.top+rect.bottom)/2};
			animation->SetKeyFrameRect(rect,rectTo);              //设置位移
			animation->BindObject(this);                          //绑定动画对象
			animation->SetReverse(false);                         //设置正反向播放,如果不明白改变一下属性试试有什么效果
			animation->SetLoop(false);                            //设置是否循环播放
			animation->RegistListener(closeListener);             //绑定监听器
			animation->PlayAnimation();                           //开始播放
		}

	}
}

创建动画对象后,设置时间、位移、正反序等属性,绑定驱动对象以及添加监听器,完成这一系列初始化操作后就可以播放了,在播放过程中还可以任意修改动画属性。

下面是skillcore和Demo的下载链接:

skillcore动画Demo下载

如有问题,或者建议请联系作者:Skilla(QQ:848861075)

时间: 2024-10-13 23:14:46

DirectUI通用动画框架的相关文章

Unity3D通用UI框架

目标:编写一个简单通用UI框架用于管理页面和完成导航跳转最终的实现效果请拉到最下方查看 框架具体实现的功能和需求 加载,显示,隐藏,关闭页面,根据标示获得相应界面实例 提供界面显示隐藏动画接口 单独界面层级,Collider,背景管理 根据存储的导航信息完成界面导航 界面通用对话框管理(多类型Message Box) 便于进行需求和功能扩展(比如,在跳出页面之前添加逻辑处理等) 编写UI框架意义 打开,关闭,层级,页面跳转等管理问题集中化,将外部切换等逻辑交给UIManager处理 功能逻辑分散

[转]IFTTT开源Swift编写的帧动画框架--RazzleDazzle

RazzleDazzle 是IFTTT开源的一个iOS帧动画框架,用Swift编写,非常适用于APP初次使用时的介绍和引导信息.RazzleDazzle由IFTTT此前开源的一款Objective-C滚动帧动画库JazzHands发展而来.JazzHands是UIKit一个简单的关键帧基础动画框架,可通过手势.scrollview.KVO或者ReactiveCocoa控制动画,被IFTTT应用在IFTTT for iPhone上.多款知名应用程序都使用了JazzHands这个框架,目前其在git

详解Qt的动画框架(一)

Qt的动画框架是在4.6版本引入的.通过Qt动画属性,Qt动画框架为部件和其他QObject对象的动画操作提供了非常大的自由性.Qt动画框架也能用于图形视图框架中.以下是Qt中的有关动画框架类的类视图: Qt的动画框架的Base是由QAbstactionAnimation以及它的两个子类QVariantAnimation和QAnimationGroup组成.QAbstractAnimation类是所有动画类的祖先.它包含了一些在框架中被普遍使用的基本功能:尤其是启动.停止和暂停动画功能.它也接收

详解Qt动画框架(2)--- 实现网易云音乐tag切换

在详解Qt的动画框架(一)介绍了关于Qt动画框架一些基础知识,在这一节中,将会实际的看到有关与动画框架的实现,该案例主要实现的具体是网易云音乐tag的切换,网易云音乐中的切换如图所示: 本文介绍的方法也可以达到这种切换的简易效果. 设计动画框架 首先我们需要设计对于动画框架,其需要的动画效果是什么?对于上图,我们需要的是三个tag可以不停的切换,可以抽象为左移以及右移,即一个tag从一个矩形区域,移动到另外的矩形区域,那么对于Tag的承载体选为什么较为合适呢?因为我们仅仅只需要图片的显示,因此Q

js动画框架设计

题记: 当你不再依赖JQuery时,当你已经厌倦了引入js类库实现一些动画效果的方式,当你想实现一个简单而实用的动画框架......下面介绍下愚人设计的动画框架:支持动画缓动算法函数,如Linear.Cubic.Back.Bounce,支持改变高度,宽度,透明度,边框,外边距的基本动画,支持动画的回调函数,如开始.暂停.完成的callback等. Section One 游戏动画,Flash动画里一个比较重要的概念是帧频,即每秒播放多少帧动画,一般动画是30帧/秒,单位为fps(frames p

linux 通用时钟框架CCF

linux 通用时钟框架CCF 简介 这里讲的时钟是给soc各组件提供时钟的树状框架,并不是内核使用的时间,和其他模块一样,clk也有框架,用以适配不同的平台.适配层之上是客户代码和接口,也就是各模块(如需要时钟信号的外设,usb等)的驱动.适配层之下是具体的soc平台的时钟操作细节. 内核中另外一个具有类似树状框架特点的是regulator框架.对比regulator框架,clk框架不确定性更大,内核中仅仅提供了少数的适配规范,struct clk都是各平台自己的clk驱动实现.       

Qt移动应用开发(二):使用动画框架

上一篇博客介绍了如何使用Qt的QML来对屏幕分辨率大小进行适应,事实上,不同分辨率的适应是一个非常棘手的问题,除了分辨率不同外,宽高比(aspect ratio)也不尽相同.有些平板在硬件上做得和IPad一样是Retina屏(2048×1536),有些低端的手机分辨率只有320×480,这样宽高比又不一样了,所以在设计App的过程一定要对内容布局有所规划.采用锚布局的方法可以帮我们解决一定的问题,同时也要善用Screen类的成员来获得系统分辨率的更多信息. 这篇文章主要介绍的是QtQuick的动

query通用开源框架

Jquery通用开源框架之[ejq.js] 简介 ejq是一款非常小巧的JS工具库,未压缩才50K,在jquery的基础上对jquery缺失部分作了很好的弥补作用. 优点: 1.具有内置的模板解析引擎语法和angularjs相近减少学习成本 2.能够方便的对JSON操作,增删查改 3.随机数功能比较健全 4.丰富的通用函数,这些函数是通过N多项目需求并且积累下来的,实用性很强. 功能介绍 一.随机数 var num= $.random.getNum(10);//获取0-10之间的随机数字 var

60.Android通用流行框架大全

转载:https://segmentfault.com/a/1190000005073746 Android通用流行框架大全 1. 缓存 名称 描述 DiskLruCache Java实现基于LRU的磁盘缓存 2.图片加载 名称 描述 Android Universal Image Loader 一个强大的加载,缓存,展示图片的库 Picasso 一个强大的图片下载与缓存的库 Fresco 一个用于管理图像和他们使用的内存的库 Glide 一个图片加载和缓存的库 3. 图片处理 名称 描述 Pi