【WPF学习】第四十八章 理解WPF动画
在许多用户框架中(特别是wpf之前的框架,如windows窗体和mfc),开发人员必须从头构建自己的动画系统。最常用的技术是结合使用计时器和一些自定义的绘图逻辑。wpf通过自带的基于属性的动画系统,改变了这种情况。接下来的两节将描述这两者之间的区别。
一、基于时间的动画
假如需要旋转windows窗体应用程序中的about对话框中的一块文本。下面是构建该解决方案的传统方法:
(1)创建周期性触发的计时器(例如,每隔50毫秒触发一次)。
(2)当触发计时器时,使用事件处理程序计算一些与动画相关的细节,如新的旋转角度。然后使窗口的一部分或者整个窗口无效。
(3)不久后,windows将要求窗口重新绘制自身,触发自定义的绘图代码。
(4)在自定义的绘图代码中,渲染旋转后的文本。
尽管这个基于计时器的解决方案不难实现,但将它继承到普通的应用程序窗口中却非常麻烦。下面是列出这种解决方案存在的一些问题:
- 绘制像素而不是控件。为旋转windows窗体中的文本,需要低级的gdi+绘图支持。gdi+易于使用,但却不能与普通的窗口元素(如按钮、文本框和标签等)很好地相互协调。所以需要将动画内容二环控件相互分离,并且不能在动画中包含任何用户交互元素。将无法旋转按钮。
- 假定单一动画。如果决定希望同时运行两个动画,就需要重新编写所有动画代码——并且变得更复杂。在这方面wpf显得更加强大,它可以构建比单一简单动画更复杂的动画。
- 动画帧率是固定的。计时器设置完全决定了帧率。如果改变时间间隔,可能需要修改动画代码(取决于执行计算的方式)。而且,选择的固定帧率对于特定的计算机显卡硬件不一定理想。
- 复杂动画需要指数级增长的更复杂的代码。旋转文本的示例非常简单,但如果想沿着一定路径移动比较小的矢量图画,就困难得多了。在wpf中,甚至是复杂的动画也能够在xaml中定义(而且可以使用第三方设计工具生成动画)。
基于计时器的动画仍存在一些缺点:导致代码不是很灵活,对于复杂的效果会变得杂乱无章,并且不鞥能得到最佳性能。
二、基于属性的动画
wpf提供了一个更高级的模型,通过该模型可以只关注动画的定义,而不必考虑它们的渲染方式。这个模型基于依赖项属性基础架构。本质上,wpf动画只不过是在一定时间间隔内修改依赖项属性值得一种方式。
例如,为了增大或缩小按钮,可以在动画中修改按钮的宽度。为使按钮闪烁,可修改用于按钮背景的lineargradientbrush画刷的属性。创建正确动画的秘密在于决定需要修改什么属性。
如果希望实现不能通过修改属性实现的其他变化,上述方法就行不通。例如,不能将添加或删除元素作为动画的一部分。同样,不要求wpf在开始场景和结束场景之间执行过渡(尽管一些灵活的变通方法可以模拟这种效果)。最后,只能依赖项属性应用动画,因为只有依赖项属性应用动画,因为只有依赖项属性使用动态的属性识别系统,而该系统将动画考虑在内。
乍一看,wpf动画关注属性的本质看起来有很大的局限性。然而,当使用wpf进行工作时,就会发现它的功能非常强大。实际上,使用每个元素都支持的公共属性可以实现非常多得动画效果。
但许多情况下,基于属性的动画系统不能工作。作为经验法则,基于属性的动画系统是为普通的windows应用程序添加动态的极佳方式。例如,如果希望润色交互性购物工具的前端,基于属性的动画系统将会很完美地工作。然而,如果需要作为应用程序的核心目标苏菲使用动画,并且希望动画在应用程序的整个生命周期中持续运行,可能需要更灵活的、更强大的技术。例如,如果正在创建基本游戏或为模型碰撞使用复杂的物理计算,就需要更好地控制动画。