【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应用程序添加动态的极佳方式。例如,如果希望润色交互性购物工具的前端,基于属性的动画系统将会很完美地工作。然而,如果需要作为应用程序的核心目标苏菲使用动画,并且希望动画在应用程序的整个生命周期中持续运行,可能需要更灵活的、更强大的技术。例如,如果正在创建基本游戏或为模型碰撞使用复杂的物理计算,就需要更好地控制动画。

  

原文地址:https://www.cnblogs.com/Peter-Luo/p/12364385.html

时间: 2024-11-05 02:22:34

【WPF学习】第四十八章 理解WPF动画的相关文章

【WPF学习】第二十八章 程序集资源

原文:[WPF学习]第二十八章 程序集资源 WPF应用程序中的程序集资源与其他.NET应用程序中的程序集资源在本质上是相同的.基本概念是为项目添加文件,从而Visual studio可将其嵌入到编译过的应用程序的EXE或DLL文件中.WPF程序集资源与其他应用程序中的程序集资源之间的重要区别是引用他们的寻址系统不同. 在前面章节已讨论过程序集资源的工作原理.因为每次编译应用程序时,项目中的每个XAML文件都转换为解析效率更高的BAML文件.这些BAML文件作为独立资源嵌入到程序集中.添加自己的资

【WPF学习】第五章 理解WPF的布局

在Windows开发人员设计用户界面的方式上,WPF布局模型是一个重大改进.在WPF问世之前,Windows开发人员使用刻板的基于坐标的布局将控件放到正确位置.在WPF中,这种方式虽然可行,但已经极少使用.大多数应用程序将使用类似Web的流(flow)布局:在使用流布局模型时,控件可以扩大,并将其他控件挤到其他位置.开发人员能创建与现实分辨率和窗口大小无关的.在不同的显示器上正确缩放的用户界面:当窗口内容发生变化时,界面可调整自身,并且可以自如地处理语言的切换.要利用该系统的优势,首先需要进一步

【WPF学习】第十八章 多点触控输入

多点触控(multi-touch)是通过触摸屏幕与应用程序进行交互的一种方式.多点触控输入和更传统的基于笔(pen-based)的输入的区别是多点触控识别手势(gesture)——用户可移动多根手指以执行常见操作的特殊方式.例如,在触摸屏上放置两根手指并同时移动他们,这通常意味着“放大",而以一根手指为支点转动另一根手指意味着"旋转".并且因为用户直接在应用程序窗口中进行这些手势,所以每个手势自然会被连接到某个特定的对象.例如,简单的具有多点触控功能的应用程序,可能会在虚拟桌

【WPF学习】第十五章 WPF事件

前两章学习了WPF事件的工作原理,现在分析一下在代码中可以处理的各类事件.尽管每个元素都提供了许多事件,但最重要的事件通常包括以下5类: 生命周期事件:在元素被初始化.加载或卸载时发生这些事件. 鼠标事件:这些事件是鼠标动作的结果. 键盘事件:这些事件是键盘动作(如按下键盘上的键)的结果. 手写笔事件:这些事件是使用类似钢笔的手写笔的结果.在平板电脑上用手写笔代替鼠标. 多点触控事件:这些事件是一根或多根手指在多点触控屏上触摸的结果.尽在Windows7中支持这些事件. 一.生命周期事件 当首次

【WPF学习】第二十四章 基于范围的控件

原文:[WPF学习]第二十四章 基于范围的控件 WPF提供了三个使用范围概念的控件.这些控件使用在特定最小值和最大值之间的数值.这些控件--ScrollBar.ProgressBar以及Slider--都继承自RangeBase类(该类又继承自Control类).尽管它们使用相同的抽象概念(范围),但工作方式却又很大的区别. 下表显示了RangeBase类定义的属性: 表 RangeBase类的属性 通常不比直接使用ScrollBar控件.更高级的ScrollViewer控件(封装了两个Scro

【WPF学习】第十四章 事件路由

原文:[WPF学习]第十四章 事件路由 由上一章可知,WPF中的许多控件都是内容控件,而内容控件可包含任何类型以及大量的嵌套内容.例如,可构建包含图形的按钮,创建混合了文本和图片内容的标签,或者为了实现滚动或折叠的显示效果而在特定容器中放置内容.设置可以多次重复嵌套,直至达到你所希望的层次深度.如下所示: <Window x:Class="RouteEvent.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2

【WPF学习】第二十九章 元素绑定——将元素绑定到一起

原文:[WPF学习]第二十九章 元素绑定--将元素绑定到一起 数据banding的最简单情形是,源对象时WPF元素而且源属性是依赖性属性.前面章节解释过,依赖项属性具有内置的更改通知支持.因此,当在源对象中改变依赖项属性的值时,会立即更新目标对象中的绑定属性.这正是我们所需要的行为--而且不必为此构建任何额外的基础结构. 为理解如何将一个元素绑定到另一个元素,下面创建一个简单的示例.该示例窗口包含了两个控件:一个Slider控件和一个具有单行文本的TextBlock控件.如果向右拖动滑动条上的滑

【WPF学习】第十九章 控件类

原文:[WPF学习]第十九章 控件类 WPF窗口充满了各种元素,但这些元素中只有一部分是控件.在WPF领域,控件通常被描述为与用户交互的元素--能接收焦点并接受键盘或鼠标输入的元素.明显的例子包括文本框和按钮.然而,这个区别有时有些模糊.将工具提示视为控件,因为它根据用户鼠标的移动显示或消失.将标签视为控件,因为它支持记忆码(mnemonics,将焦点转移到相关控件快捷键). 所有控件都继承自System.Windows.Control类,该类添加了一小部分基本的基础结构: 设置控件内容对齐方式

【WPF学习】第二十六章 Application类——应用程序的生命周期

原文:[WPF学习]第二十六章 Application类--应用程序的生命周期 在WPF中,应用程序会经历简单的生命周期.在应用程序启动后,将立即创建应用程序对象,在应用程序运行时触发各种应用程序事件,你可以选择监视其中的某些事件.最后,当释放应用程序对象时,应用程序将结束. 一.创建Application对象 使用Application类的最简单方式是手动创建它.下面的示例演示了最小的程序:在应用程序入口(Main()方法)处创建名为MainWindow的窗口,并启动一个新的应用程序: 在本质