8.1 动画方案的选择

Windows Phone的动画实现方式有线性插值动画(3种类型)、关键祯动画(4种类型)和基于帧动画,甚至还有定时器动画,然后动画所改变的UI元素属性可以是普通的UI元素属性,变换特效属性和三维特效属性,面对着这么多的选择,我们要实现一个动画效果该怎么去思考动画实现的思路以及怎么选择实现的技术呢?那么我们这小节会先讲解与动画性能相关的知识,然后再讲解怎么去选择动画的实现方案。

8.1.1 帧速率

帧速率是用于测量显示帧数的量度,测量单位为“每秒显示帧数”(Frame per Second,FPS,帧率)或“赫兹”,是指每秒钟刷新的画面的帧数,也可以理解为图形处理器每秒钟能够刷新几次。由于人类眼睛的特殊生理结构,如果所看画面之帧率高于每秒约10-12帧的时候,就会认为是连贯的。对于动画而言,帧速率常用于衡量动画的流畅度,帧速率的数字越大表示动画的流畅度越高。在实现Windows Phone动画的时候,我们是不能够直接指定动画的帧速率的,动画的帧速率是由系统自动分配的,当手机的性能越好,程序的性能越好,那么动画的帧速率就越大,反之就越小。所以要判断一个动画是否能够流畅地运行,我们需要关注动画的帧速率指标是否足够高。

在Windows Phone里面虽然不能够直接设置动画的帧速率,但是可以测量出来。当在Windows Phone模拟器中运行应用时,可以使用帧速率计数器来监控应用的性能和动画的效率,模拟器的效果图如图8.1所示,每一个帧速率计数器的作用如表8.1所示。当然帧速率计数器也一样可以在手机上进行显示,在真实的 Windows Phone 手机上测试这些计数器非常重要,因为模拟器的性能和在真实的手机上是有很大区别的。对于每个计数器的值都有建议阈值和上限阈值,如表8.2所示,当计数器在红色值阈值区间表明存在潜在性能问题,这就需要引起重视,你的动画的实现方案可能有较大的问题,需要进行优化。

表8.2 建议的帧和填充速率

计数器

红色阈值*

建议值

上限阈值

构图线程帧速率

30 帧/秒

45 帧/秒

60 帧/秒

UI 线程帧速率

15 帧/秒

30 帧/秒

60 帧/秒

屏幕填充速率

>3

<= 2.5

3.0

那么帧速率计数器是可以在代码中启用或禁用的,当你在Visual Studio中创建 Windows Phone应用项目时,默认情况下会在文件 App.xaml.cs 中添加启用帧速率计数器的代码。代码如下所示:

if (System.Diagnostics.Debugger.IsAttached)

{

this.DebugSettings.EnableFrameRateCounter = true;

}

上面的代码表示当启动Debug状态调试应用程序的时候将会启用帧速率计数器。其中Application.Current.Host.Settings.EnableFrameRateCounter = true表示启用帧速率计数器,设置为false则禁用帧速率计数器。

8.1.2 UI线程和构图线程

Windows Phone的图形线程结构针对手机进行了优化,除了UI线程之外,Windows Phone 还支持构图线程。若要掌握怎么去选择最优的动画实现方案,那么需要理解Windows Phone 中UI线程和构图线程,这对做动画的优化是非常重要的。

(1)UI 线程

UI 线程是Windows Phone中的主线程,UI线程的主要任务是从 XAML 中分析并创建对象、在第一次绘制视觉效果时,将绘制所有视觉效果以及处理每帧回调并执行其他用户代码。在应用程序里面维护轻量级的UI线程是保障应用程序流畅运行的前提,同时这对于动画的实现也是一样的道理,尽量避免占用UI线程。

    (2)构图线程

构图线程可以处理某些在UI上的工作,从而分担了UI线程的部分工作,提高Windows Phone应用的性能。在Windows Phone上,构图线程的工作是,它合并图形纹理并将其传递到 GPU 以供绘制,手机上的 GPU 将在称为自动缓存的进程中,自动缓存并处理运行在构图线程上的动画。构图线程处理与变换特效(RenderTransform)和三维特效(Projection)属性关联的动画,如针对于ScaleTransform、TranslateTransform、RotateTransform和PlaneProjection的属性改变的Storyboard动画都是完全运行在构图线程上的。另外,Opacity 和 Clip 属性设置也由构图线程处理。但是,如果使用 OpacityMask或非矩形剪辑,则这些操作将被传递到 UI 线程。

    (3)动画和线程

从构图线程的作用可以知道StoryBoard动画由构图线程进行处理,那么这种动画的处理方式最为理想,因为构图线程会将这些动画传递到GPU进行处理。如果需要在动画中使用到UI线程,如改变UI元素的With属性等,那么就需要给动画相应的Animation对象的EnableDependentAnimation属性设置为True,它表示动画是否需要依赖UI线程来运行。此外,如果 CPU 超负荷,则构图线程可能比UI线程运行的更频繁。但是,有时Storyboard动画无法实现你的动画效果的时候,你可以选择在代码中驱动动画,如采用基于帧动画。这些动画按帧进行处理,每帧回调都在UI线程上进行处理,动画的更新速度与UI线程处理动画的速度相当,并且根据应用中发生的其他操作,动画显示的流畅性可能低于在构图线程上运行的动画。另外,当使用基于帧动画在代码中更新动画时,UI元素不会像在Storyboard动画中更新一样,自动进行缓存,这又加重了UI线程的负担。

8.1.3 选择最优的动画方案

上一章我们讲解了很多的动画的变成知识,这些都是Windows Phone动画编程的根基,正所谓万变不离其宗,无论你要实现的动画懂么复杂,都离不开这些基础知识。当我们要去实现一个动画效果的时候,首先需要去思考动画中的每个组成元素,思考它们的变化情况,想一下要改变UI元素的什么属性来实现动画的效果,想一下用什么动画类型来实现。当你已经想到了有多种方案可以实现这个动画效果的时候,你可以从两个方面去衡量你的实现方案,一方面是从性能效率方面,这就涉及到前面所讲的动画的帧速率,UI线程和构图线程相关的知识;另一方面是从动画实现的复杂度方面,比如要实现一个很复杂图形的形状变化的动画,你可以直接用Path图形来绘制出这个图形,然后设计Path图形的点运动的动画,也可以用多张类似的图片做图片切换的动画,如果图片切换的动画效果能达到你所想要的效果,那么就建议使用图片切换这种简单的方式来实现。

在Windows Phone中有多种实现动画的方案,关于这些方案的选择有下面的一些建议。

(1)可以用变换特效属性或者三维特效属性实现的动画,应该尽量采用变换特效属性或者三维特效属性作为动画改变的属性去实现动画。因为变换特效属性或者三维特效属性是通过构图线程对UI元素产生作用的,不会阻塞UI线程也不会重新调用UI的布局系统。

(2)可以使用线性插值动画/关键帧动画来实现的动画就采用线性插值动画/关键帧动画去实现,因为线性插值动画/关键帧动画是最优的动画实现方式,它们本身也是在构图线程上运行的。

(3)当使用线性插值动画/关键帧动画无法实现的动画效果的时候应该采用基于帧动画来实现,而不是自定义定时器来实现动画,基于帧动画比定时器动画更胜一筹,它可以根据设备和应用程序的情况动态地跳帧调用的频率。

下面我们通过一个例子来演示用两种不同的方法来实现一个相同的动画效果,所实现的动画效果是让矩形的高度慢慢地变成原来的两倍,第一种方式是用线性插值动画对矩形的Height属性进行动画处理,第二种方式也是用线性插值动画,但是针对的动画目标属性是ScaleTransform的ScaleY属性,然后我们用一个按钮点击事件阻塞UI线程2秒钟,可以看到针对Height属性的动画会暂停2秒钟再继续运行,而针对ScaleTransform的ScaleY属性不会受UI线程阻塞的影响。示例代码如下所示:

代码清单8-1两种动画的对UI线程的影响(源代码:第8章\Examples_8_1)

MainPage.xaml文件主要代码
------------------------------------------------------------------------------------------------------------------< Page.Resources><Storyboard x:Name="heightStoryboard"><!--针对Height属性的动画--><DoubleAnimation Storyboard.TargetName="rectangle1" Storyboard.TargetProperty="Height" RepeatBehavior="Forever" EnableDependentAnimation="True" From="100" To="200" Duration="0:0:2">        </DoubleAnimation></Storyboard><Storyboard x:Name="scaleTransformStoryboard"><!--针对ScaleTransform的ScaleY属性的动画--><DoubleAnimation Storyboard.TargetName="scaleTransform1" Storyboard.TargetProperty="ScaleY"  RepeatBehavior="Forever" From="1" To="2" Duration="0:0:2"></DoubleAnimation></Storyboard></ Page.Resources><StackPanel><Button Content="阻塞UI线程" Click="Button_Click_1"></Button><Button x:Name="heightAnimationButton" Content="Height属性动画"  Click="heightAnimationButton_Click_1"></Button><Button x:Name="scaleTransformAnimationButton" Content="ScaleTransform属性动画"  Click="scaleTransformAnimationButton_Click_1"></Button><Rectangle Height="100" Fill="Blue" x:Name="rectangle1"><Rectangle.RenderTransform><ScaleTransform x:Name="scaleTransform1" ></ScaleTransform></Rectangle.RenderTransform></Rectangle></StackPanel>

MainPage.xaml.cs文件主要代码
------------------------------------------------------------------------------------------------------------------private void Button_Click_1(object sender, RoutedEventArgs e){// 阻塞UI线程2秒钟Task.Delay(2000).Wait();}private void heightAnimationButton_Click_1(object sender, RoutedEventArgs e){// 播放改变高度属性的动画,高度有100变成200
        scaleTransformStoryboard.Stop();heightStoryboard.Begin();}private void scaleTransformAnimationButton_Click_1(object sender, RoutedEventArgs e){// 播放改变变换属性的动画,举行沿着X轴放大2倍
        heightStoryboard.Stop();scaleTransformStoryboard.Begin();}

本文来源于《深入理解Windows Phone 8.1 UI控件编程》

源代码下载:http://vdisk.weibo.com/s/zt_pyrfNHoezI

欢迎关注我的微博@WP林政

WP8.1技术交流群:372552293

[WP8.1UI控件编程]Windows Phone动画方案的选择相关推荐

  1. [WP8.1UI控件编程]Windows Phone自定义布局规则

    3.2 自定义布局规则 上一节介绍了Windows Phone的系统布局面板和布局系统的相关原理,那么系统的布局面板并不一定会满足所有的你想要实现的布局规律,如果有一些特殊的布局规律,系统的布局面板是 ...

  2. [WP8.1UI控件编程]SemanticZoom控件实现分组列表

    11.1.5 SemanticZoom实现分组列表 SemanticZoom控件可以让用户实现一种更加高级的列表,这种列表可以对列表的项目进行分组,同时这个SemanticZoom控件会提供两个具有相 ...

  3. delphi RichEdit控件中插入GIF动画表情

    delphi在RichEdit控件中插入GIF动画表情 在UDP即时通讯软件中实现类似于QQ的动画表情,在richEdit控件中插入gif动画表情. 发送的时候将表情转为命令,接收之后,再将命令转换为 ...

  4. MFC控件编程之复选框单选框分组框

    MFC控件编程之复选框单选框分组框 一丶分组框 分组框 英文叫做 GroubBox 添加了分组框主要就是分组.好看.不重点介绍 二丶单选框 英文: Raido Button 单选框需要注意的事项 1. ...

  5. 异步委托实现多线程winform控件编程

            private void button1_Click(object sender, EventArgs e)         {             ThreadStart ts  ...

  6. 微软的PivotViewer控件编程续

    在前一篇微软的PivotViewer控件编程中,讲到了创建PivotViewer使用的静态数据源的方法.但是手工创建CXML,或者在Excel里面一个个输入PivotViewer里面的数据的确是太麻烦 ...

  7. [K/3Cloud]进度条控件编程接口

    进度条控件编程接口 1.启动进度查询 this.GetControl<ProgressBar>().Start(2)  //每2秒查询一次进度 2.汇报进度 在插件中重载 OnQueryP ...

  8. 金蝶 K/3 Cloud 服务端控件编程模型

    如下图是服务端已有的控件编程模型 转载于:https://www.cnblogs.com/whlalhj/p/5184148.html

  9. 如何添加地图控件到Windows Phone 8的页面中

    原文 如何添加地图控件到Windows Phone 8的页面中 本主题介绍了各种方法来添加一个地图控件到Windows Phone 8的项目.该地图控件在Windows Phone的SDK 8.0的库 ...

  10. MFC控件编程之组合框跟列表框

    MFC控件编程之组合框跟列表框 一丶简介 如果要使用组合框跟列表框.那么就要知道.组合框列表框是最核心的东西就是索引. 索引是从0开始的. 二丶组合框列表框常用的方法 AddString(字符串) 添 ...

最新文章

  1. Python的subprocess子进程和管道进行交互
  2. 编写一段代码,实现在控制台输入一组数据后,排序后再控制台输出
  3. 设计优秀API的五大规则
  4. 【转】Windows8不联网直接安装.Net 3.5 Framework的方法
  5. 10 邮件槽_员工主动发离职邮件,提出申请又反悔,法院判决让人懵了!
  6. QPW 行政区划字典表(td_area)
  7. java 小数精度问题
  8. innovus停止当前命令_从命令行停止node.js程序
  9. 从伪随机数的产生到高大上的蒙特卡洛算法(C语言实现)
  10. jQuery放大镜插件
  11. 打印显示服务器存储空间不足,服务器存储空间不足,无法处理此命令。 ID 2019 或 2020...
  12. CentOS Linux解决Device eth0 does not seem to be pres
  13. 8个按键控制8个继电器c语言程序,单片机C语言程序的设计实训100例.doc
  14. 极路由3刷老毛子稳定使用锐捷教程
  15. chrome插件开发基础以及如何防止劫持
  16. Hbase、Kudu和ClickHouse横向对比V2.0
  17. 使用Axis2实现WebService的发布和调用
  18. 2019牛客暑期多校训练营(第八场) Explorer (线段树分治+区间离散化)
  19. 深究C语言4.链表和结构体
  20. MathType 运行时错误‘53’:文件未找到:MathPage.WLL

热门文章

  1. android 正五边形图表,Android自定义View-蜘蛛网属性图(五边形图)
  2. mysql查处所有表中的新数据,mysql – 对所有表执行查询并在新表中填入数据
  3. linux网络分析之回环网卡
  4. 同步与互斥的基本原理
  5. Linux内核模块静态加载的顺序
  6. ssh 远程连接失败 PTY报错
  7. Ubunt 12.04 中的QT中配置Tyin mini210 的交叉编译环境
  8. 数据结构一些自己没搞懂的点
  9. python property 与get/set方法详解
  10. hive partition 分区详解二