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

时间:2022-03-13 02:36:49

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().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();
}

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

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

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

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

WP8.1技术交流群:372552293

[WP8.1UI控件编程]Windows Phone动画方案的选择的更多相关文章

  1. &lbrack;WP8&period;1UI控件编程&rsqb;Windows Phone XAML页面的编译

    1.1.2 XAML页面的编译 Windows Phone的应用程序项目会通过Visual Studio完成XAML页面的编译,在程序运行时会通过直接链接操作加载和解析XAML,将XAML和过程式代码 ...

  2. &lbrack;WP8&period;1UI控件编程&rsqb;Windows Phone大数据量网络图片列表的异步加载和内存优化

    11.2.4 大数据量网络图片列表的异步加载和内存优化 虚拟化技术可以让Windows Phone上的大数据量列表不必担心会一次性加载所有的数据,保证了UI的流程性.对于虚拟化的技术,我们不仅仅只是依 ...

  3. &lbrack;WP8&period;1UI控件编程&rsqb;Windows Phone VirtualizingStackPanel、ItemsStackPanel和ItemsWrapGrid虚拟化排列布局控件

    11.2.2 VirtualizingStackPanel.ItemsStackPanel和ItemsWrapGrid虚拟化排列布局控件 VirtualizingStackPanel.ItemsSta ...

  4. &lbrack;WP8&period;1UI控件编程&rsqb;Windows Phone理解和运用ItemTemplate、ContentTemplate和DataTemplate

    2.2.5 ItemTemplate.ContentTemplate和DataTemplate 在理解ItemTemplate.ContentTemplate和DataTemplate的关系的之前,我 ...

  5. &lbrack;WP8&period;1UI控件编程&rsqb;Windows Phone自定义布局规则

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

  6. &lbrack;WP8&period;1UI控件编程&rsqb;SemanticZoom控件实现分组列表

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

  7. 《深入理解Windows Phone 8&period;1 UI控件编程》基于最新的Runtime框架

    <深入理解Windows Phone 8.1 UI控件编程>本书基于最新的Windows Phone 8.1 Runtime SDK编写,全面深入地论述了最酷的UI编程技术:实现复杂炫酷的 ...

  8. MFC控件编程之 按钮编辑框&period;静态文本的使用&comma;以及访问控件的七种方法&period;

    MFC控件编程之 按钮编辑框.静态文本的使用以及访问控件的七种方法. 一丶按钮.静态文本的通用属性. 他们都有一个属性.就是可以输入标题内容.以及可以自定义控件ID. 创建一个MFC Dlg对话框. ...

  9. MFC控件编程之鼠标跟键盘消息

    MFC控件编程之鼠标跟键盘消息 在MFC中鼠标消息.键盘消息我们很常用.所以说一下. 鼠标消息分为客户区消息.跟非客户区消息. 一丶客户区消息 我们可以处理消息.来进行我们相应的函数即可. MFC添加 ...

随机推荐

  1. 弹层组件-layer

    layer是Layui的一个弹层组建,功能强大,总之我很喜欢,下面介绍这个组件的基本用法. 首先如果只需要使用layer而不想使用Layui可以单独下载layer组件包,页面引入jquery1.8以上 ...

  2. 深入理解Java虚拟机之读书笔记三 内存分配策略

    一般的内存分配是指堆上的分配,但也可能经过JIT编译后被拆散为标量类型并间接地在栈上分配.对象主要分配在新生代的Eden区上,如果启动了本地线程分配缓冲,将按线程优先在TLAB上分配,少数情况下直接分 ...

  3. iOS开发——网络篇——数据安全(MD5)&comma;HTTPS,检测网络状态

    一.数据安全 1.提交用户的隐私数据一定要使用POST请求提交用户的隐私数据GET请求的所有参数都直接暴露在URL中请求的URL一般会记录在服务器的访问日志中服务器的访问日志是黑客攻击的重点对象之一 ...

  4. 解决Android时时更新listview数组越界问题

    时时更新数据一般出现在金融.股票行业对数据的准确性要求极高情况下使用. 先来看看下面一段代码, public class MainActivity extends Activity { private ...

  5. WITH AS 优化逻辑读

    SQL> select * from fxqd_list_20131115_new where (acct_no, oper_no, seqno, trans_amt) not in (sele ...

  6. WinForm ListControl MouseWheel Envent

    最近在使用Listbox开发程序的时候, 遇到MouseWheel event 异常. 设置如下: 1. DrawModel:ownerDrawVariable. 2. InternalHeight: ...

  7. 页面onclick&lpar;&rpar;中传值问题

    html中onclick()里面传变量到javascript中的问题,小小的记录下: 传变量的话一定要加  '' <span onclick="sellGoods('${session ...

  8. intellj idea 如何设置类头注释和方法注释

    intellj idea 如何设置类头注释和方法注释           intellj idea的强大之处就不多说了,相信每个用过它的人都会体会到,但是我们也会被他的复杂搞的晕头转向,尤其刚从ecl ...

  9. windows 怎样查看port占用情况

    開始--执行--cmd 进入命令提示符 输入netstat -ano 就可以看到全部连接的PID 之后在任务管理器中找到这个PID所相应的程序假设任务管理器中没有PID这一项,能够在任务管理器中选&q ...

  10. gcc或clang中消除特定警告的方法

    一般在编译代码时会有相当多的警告信息,尤其当我们使用了-Wall选项的时候.-Wall绝不是像其字面意思一样打开所有警告.不过它打开的警告也相当多了.对于一些我们已知"无害"但仍然 ...