WPF中的动画——(一)基本概念

原文:WPF中的动画——(一)基本概念

WPF的一个特点就是支持动画,我们可以非常容易的实现漂亮大方的界面。首先,我们来复习一下动画的基本概念。计算机中的动画一般是定格动画,也称之为逐帧动画,它通过每帧不同的图像连续播放,从而欺骗眼和脑产生动画效果。其原理在维基百科上有比较详尽的解释,这里就不多介绍了。

也就是说,我们要产生动画,只需要连续刷新界面即可。例如,我们要实现一个宽度变化的按钮的动画,可以用如下方式来实现:

    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        var timer = new System.Windows.Threading.DispatcherTimer();
        timer.Tick += new EventHandler(OnTimedEvent);
        timer.Interval = TimeSpan.FromSeconds(1.0 / 20);
        timer.Start();
    }

    int index = 0;
    private void OnTimedEvent(object sender, EventArgs e)
    {
        index++;
        if (index > 40)
            index = 0;

        button.Width = 8 * (index++);
    }

这段代码不难理解,就是每隔1/20秒更新一次按钮的宽度,在2s内将其高度从0变为320,重复播放。

这段代码虽然实现了动画效果,但它是通过计时器更新的传统做法,在WinForm下也能实现。在WPF中,正统的实现动画方式为:

    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        var widthAnimation = new DoubleAnimation()
        {
            From = 0,
            To = 320,
            Duration = TimeSpan.FromSeconds(2),
            RepeatBehavior = RepeatBehavior.Forever,
        };

        button.BeginAnimation(WidthProperty, widthAnimation);
    }

相比较而言,WPF的动画的实现方式有如下优点:

一、简洁

这个是非常明显的,WPF的动画的代码非常容易理解,Timer的版本则要难懂得多。当然,我们也可以通过封装,使得用Timer也能用类似的API实现动画。但动画的API并不是仅仅这么一点,要把整个动画框架的API都封装也没有那么容易。

二、和XAML无缝集成

这个就是WPF的独有技术了,得益于XAML强大的表述能力,我们可以写出非常强大且容易维护的动画。(这里就不举例了,后续文章中再做介绍)这点WinFom的Timer版本是无法做到的。

三、流畅性

如果将这两种实现方式一起跑起来比较一下就会发现,Timer实现的版本明显要卡顿,并且并没有精准的按照我们设计的那样运动。具体原因为:

Timer精度的问题:由于是改UI控件的属性(按钮的宽度),因此必须在UI线程上进行,因此DispatcherTimer 操作与其他操作一样需要放置到 Dispatcher 队列中,它并不保证恰好在改时间间隔中。它并不适合动画这种间隔很短的计时。

帧率的问题:逐帧动画的流畅性一般取决于每秒更新的帧数,也就是常说的帧率。人眼睛上限是70帧,而我这里代码中的Timer的固定了为20帧,因此是能明显感觉到卡顿的。而WPF的动画则不然,从它的API中可以看到,它是没有帧率的设置的。实际上,它是根据计算机的性能和当前进程的繁忙程度尽可能增大帧率的,因此WPF的动画是远大于20帧的,因此要流畅得多。

那么,是否只要修改参数,加大Timer的版本的帧率,也可以实现同样流畅的动画呢? 试了一下,就算修改参数,也是无法达到WPF版本的流畅程度的。我认为原因主要有如下两点,

  1. DispatcherTimer精度不够,无法实现大帧率下准确刷新。
  2. 通过简单的设置参数很难像WPF那样帧率根据计算机的性能和当前进程的繁忙程度智能匹配帧率。帧率设置过低,动画不流畅,设置过大,处理不过来仍然不流畅。并且UI线程的忙碌程度是会动态变化的,帧率也需要相应调整,这些都无法通过Timer来简单的处理。

总之,通过Timer定时更新的方式并不适合用来实现动画。因此还是有必要学习一下WPF的动画框架的,后面我将陆续写一系列文章进行一些简单的介绍。如果要系统的学习,建议参看以下微软的官方文档: http://msdn.microsoft.com/zh-cn/library/ms752312(v=vs.110).aspx

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/390454.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

cloud 异步远程调用_异步远程工作的意外好处-以及如何拥抱它们

cloud 异步远程调用In this article, Ill discuss the positive aspects of being a little out of sync with your team.在本文中,我将讨论与您的团队有点不同步的积极方面。 So you’ve started working from home.因此,您已经开始在家工作。 There …

linux 问题一 apt-get install 被 lock

问题: sudo apt-get install vim E: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavailable)E: Unable to lock the administration directory (/var/lib/dpkg/), is another process using it? 解决: sudo rm /var/cac…

工信部高级软件工程师_作为新软件工程师的信

工信部高级软件工程师Dear Self, 亲爱的自我, You just graduated and you are ready to start your career in the IT field. I cannot spoil anything, but I assure you it will be an interesting ride. 您刚刚毕业,就可以开始在IT领域的职业了。 我…

Python高级网络编程系列之基础篇

一、Socket简介 1、不同电脑上的进程如何通信? 进程间通信的首要问题是如何找到目标进程,也就是操作系统是如何唯一标识一个进程的! 在一台电脑上是只通过进程号PID,但在网络中是行不通的,因为每台电脑的IP可能都是不一…

多线程编程和单线程编程_生活与编程的平行线程

多线程编程和单线程编程I’m convinced our deepest desire is, by paying the cost of time, to be shown a glimmer of some fundamental truth about the universe. To hear it whisper its lessons and point towards its purpose.我坚信,我们最深切的愿望是通过…

剑指 Offer 67. 把字符串转换成整数

写一个函数 StrToInt,实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。 当我们寻找到的第一个非空字符为正或者负号时&#xff0c…

搭建MSSM框架(Maven+Spring+Spring MVC+MyBatis)

https://github.com/easonjim/ssm-framework 先欠着&#xff0c;后续再进行讲解&#xff1a; 一、Spring内核集成 二、Spring MVC集成 三、MyBatis集成 四、代码生成工具集成 >如有问题&#xff0c;请联系我&#xff1a;easonjim#163.com&#xff0c;或者下方发表评论。<…

4.RabbitMQ Linux安装

这里使用的Linux是CentOS6.2 将/etc/yum.repo.d/目录下的所有repo文件删除 先下载epel源 # wget -O /etc/yum.repos.d/epel-erlang.repo http://repos.fedorapeople.org/repos/peter/erlang/epel-erlang.repo 修改epel-erlang.repo文件&#xff0c;如下图 添加CentOS 的下载源…

freecodecamp_如何对freeCodeCamp文章提供反馈

freecodecampWe at the freeCodeCamp editorial team do our best to ensure articles are as accurate as they can be.我们的freeCodeCamp编辑团队竭尽所能&#xff0c;以确保文章尽可能准确。 Still, we occasionally miss factual inaccuracies, non-functioning code exa…

如何对接oracle 建立pdb

Oracle数据库的结构是一个数据库实例下有许多用户&#xff0c;每一个用户有自己的表空间&#xff0c;即每一个用户相当于MySQL中的一个数据库。不久前下了oracle 12c的数据库&#xff0c;安装之后建user时才知道oracle12c 有一个很大的变动就是引入了pdb可插入数据库&#xff0…

二、数据库设计与操作

一、 数据库设计仿QQ数据库一共包括5张数据表&#xff0c;每张数据表结构如下&#xff1a;1、 tb_User&#xff08;用户信息表&#xff09;这张表主要用来存储用户的好友关系与信息字段名数据类型是否Null值默认值绑定描述IDint否用户账号PwdVarchar(50)否用户密码Frie…

hdu 过山车_从机械工程师到软件开发人员–我的编码过山车

hdu 过山车There arent many people out there who grew up dreaming of writing code. I definitely didnt. I wanted to design cars. But somehow I ended up building software.很少有人梦见编写代码。 我绝对没有。 我想设计汽车。 但是我最终以某种方式开发了软件。 I u…

mysql 两列互换

mysql 如果想互换两列的值&#xff0c;直接写 update 表 set col1col2&#xff0c;col2col1 这样的后果就是两列都是 col2 的值 注意这和sql server 是不同的&#xff0c; 如果想实现上述功能&#xff0c;添加一个自增列作为标识&#xff08;必须的&#xff09;&#xff0c; u…

剑指 Offer 36. 二叉搜索树与双向链表

输入一棵二叉搜索树&#xff0c;将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点&#xff0c;只能调整树中节点指针的指向。 为了让您更好地理解问题&#xff0c;以下面的二叉搜索树为例&#xff1a; 我们希望将这个二叉搜索树转化为双向循环链表。链表…

游戏引擎开发和物理引擎_视频游戏开发的最佳游戏引擎

游戏引擎开发和物理引擎In this article, well look at some of the most popular game engines for video game development. Youll get a brief overview of each engine so you can choose which to use for your project.在本文中&#xff0c;我们将介绍一些用于视频游戏开…

TPS和QPS的区别和理解

TPS和QPS的区别和理解 原创 2016年04月26日 17:11:3114010QPS&#xff1a;Queries Per Second意思是“每秒查询率”&#xff0c;是一台服务器每秒能够相应的查询次数&#xff0c;是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。 TPS&#xff1a;是Transaction…

1893. 检查是否区域内所有整数都被覆盖

theme: healer-readable 给你一个二维整数数组 ranges 和两个整数 left 和 right 。每个 ranges[i] [starti, endi] 表示一个从 starti 到 endi 的 闭区间 。 如果闭区间 [left, right] 内每个整数都被 ranges 中 至少一个 区间覆盖&#xff0c;那么请你返回 true &#xff…

004-docker常用命令[二]-容器操作ps,top,attach,export

2.3、容器操作 2.3.1、docker ps docker ps : 列出容器 语法 docker ps [OPTIONS] OPTIONS说明&#xff1a; -a :显示所有的容器&#xff0c;包括未运行的。 -f :根据条件过滤显示的内容。 --format :指定返回值的模板文件。 -l :显示最近创建的容器。 -n :列出最近创建的n…

【类】变量复用,函数复用

变量复用 变量复用&#xff0c;适用于以下场景&#xff1a;1&#xff0c;整个项目公用的部分&#xff08;比如errors&#xff09;&#xff1b;2&#xff0c;一组类要通信&#xff0c;或者同一个类的两个函数之间要通信&#xff0c;通信数据可以用类来定义和约束&#xff1b; 场…

python练习_如何使用Logzero在Python中练习记录

python练习Logzero is a Python package created by Chris Hager that simplifies logging with Python 2 and 3. Logzero makes it easier as a print statement to show information and debugging details.Logzero是Chris Hager创建的Python程序包&#xff0c;它简化了Pytho…