【WPF学习笔记】[转]周银辉之WPF中的动画 晓风影天之wpf动画——new PropertyPath属性链...

(一)WPF中的动画

 

动画无疑是WPF中最吸引人的特色之一,其可以像Flash一样平滑地播放并与程序逻辑进行很好的交互。这里我们讨论一下故事板。

在WPF中我们采用Storyboard(故事板)的方式来编写动画,为了对Storyboard有个大概的印象,你可以粘贴以下代码到XamlPad来查看效果:

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"WindowTitle="Storyboards Example"><StackPanel Margin="20"><Rectangle Name="MyRectangle"Width="100"Height="100"><Rectangle.Fill><SolidColorBrush x:Name="MySolidColorBrush" Color="Blue" /></Rectangle.Fill><Rectangle.Triggers><EventTrigger RoutedEvent="Page.Loaded"><BeginStoryboard><Storyboard RepeatBehavior="Forever" AutoReverse="True"><DoubleAnimation Storyboard.TargetName="MyRectangle"Storyboard.TargetProperty="Width"From="100" To="200" Duration="0:0:1" />              </Storyboard></BeginStoryboard></EventTrigger></Rectangle.Triggers></Rectangle> </StackPanel>
</Page>

在介绍Storyboard之前应该先了解Animation
Animation提供一种简单的“渐变”动画,我们为一个Animation指定开始值和一个结束值,并指定由开始值到达结束值所需的时间,便可形成一个简单的动画。比如我们指定长方形的宽度由100变化到200,所需时间为1秒,很容易想像这样的动画是什么样的,而它对应的Xaml代码如下:

            <DoubleAnimation Storyboard.TargetName="MyRectangle"Storyboard.TargetProperty="Width"From="100" To="200" Duration="0:0:1" />

将它翻译成C#代码则如下:

            DoubleAnimation myDoubleAnimation = new DoubleAnimation();myDoubleAnimation.From = 100;myDoubleAnimation.To = 200;myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.WidthProperty));

代码里我们定义了一个DoubleAnimation,并指定了它的开始值和结束值以及它由开始值到达结束值所需的时间。至于后面两句,它们是用来将Aniamtion与指定的对象和指定的属性相关联,等会我们将介绍。
注意到,这里我们使用的是DoubleAnimation,因为我们所要变化的是数值。那么如果我们要变化颜色是不是就用ColorAnimation了呢,对,其实出了这些之外还有PointAnimation等等,并且你可以实现IAnimatable接口来实现自定义版本的Animation。关于这些你可以参见System.Windows.MediaAniamtion名字空间.

但值得注意的是并非每个属性都能够使用Animation,它必须满足以下条件:
1,它必须是Dependency Property
2,它所在类必须继承于DependencyObject,必须实现了IAnimatable接口.
3,必须有类型一致的Animation Type(即Color类型使用ColorAniamtion,Point类型使用PointAnimation等)

一个简单的Animation定义了一个简单的动画,很容易想到的是,如果若干个Animation同时作用于一个对象,那么这个对象不就可以表现复杂的动画了吗,对,这就是Storyboard

Storyboard可以看做是Animation的容器,它包含了若干的简单动画来完成一个复杂动画。
参考以下代码:

<!-- This example shows how to animate with a storyboard.-->
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"WindowTitle="Storyboards Example"><StackPanel Margin="20"><Rectangle Name="MyRectangle"Width="100"Height="100"><Rectangle.Fill><SolidColorBrush x:Name="MySolidColorBrush" Color="Blue" /></Rectangle.Fill><Rectangle.Triggers><EventTrigger RoutedEvent="Page.Loaded"><BeginStoryboard><Storyboard RepeatBehavior="Forever" AutoReverse="True"><DoubleAnimation Storyboard.TargetName="MyRectangle"Storyboard.TargetProperty="Width"From="100" To="200" Duration="0:0:1" />    <ColorAnimation Storyboard.TargetName="MySolidColorBrush"Storyboard.TargetProperty="Color"From="Blue" To="Red" Duration="0:0:1" />            </Storyboard></BeginStoryboard></EventTrigger></Rectangle.Triggers></Rectangle> </StackPanel>
</Page>

这里我们的Storyboard定义了DoubleAnimation来变化矩形的宽度,并定义了ColorAnimation来变化矩形的颜色。

至此,你已经可以编写绚丽的WPF动画了,并推荐你下载Expression Blend来制作WPF动画.



但你会发现使用XAML标记的方式来编写动画虽然很简单,但缺乏了C#等程序设计语言的灵活性,比如我们的矩形动画中矩形的宽度是由后台逻辑计算出来的变量值,我们的动画将如何编写呢,这时我更喜欢使用C#的方式来编写动画,虽然这所需的代码量更大.
以下重点介绍如何用C#编写动画,并且这更助于你理解Storyboard是如何工作的。

参考以下代码:

            this.Name = "PageMain";myRectangle.Name = "MyRectangle";  NameScope.SetNameScope(this, new NameScope());                      this.RegisterName(myRectangle.Name, myRectangle);DoubleAnimation myDoubleAnimation = new DoubleAnimation();myDoubleAnimation.From = 100;myDoubleAnimation.To = 200;myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.WidthProperty));Storyboard myStoryboard = new Storyboard();myStoryboard.Children.Add(myDoubleAnimation);this.Loaded += delegate(object sender, MouseEventArgs e){myStoryboard.Begin(this);};

其中:

 

            DoubleAnimation myDoubleAnimation = new DoubleAnimation();
            myDoubleAnimation.From = 100;
            myDoubleAnimation.To = 200;
            myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
定义了一个DoubleAniamtion,并指定了它的开始值和结束值以及所需的时间.
Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);设置myDoubleAniamtion的作用对象是"myRectangle",注意到传入的第二个参数是一个字符串myRectangle.Name,那么我们的程序怎么知道"myRectangle"这个字符串就是指我们的矩形对象myRectangle呢,这里存在一个名称与对象的映射,即我们的"myRectangle"映射到矩形对象myRectangle,为了构造这个映射我们涉及到了NameScope(名字域)这个概念.
            NameScope.SetNameScope(this, new NameScope());                      
            this.RegisterName(myRectangle.Name, myRectangle);
上面的代码中,this设置了一个名字域,myRectagle向这个名字域注册了自己的名字,这样我们的程序就可以通过this的名字域来查找到myRectangle与"myRectangle"之间的映射关系了,关于NameScope可以参见MSDN WPF Namescopes主题.
为了让myDoubleAnimation知道它所作用的属性是谁,我们使用Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.WidthProperty));语句来将Aniamtion与属性关联起来,其中PropertyPath中指定要作用的对象所对应的DependencyProperty.
然后我们将定义好的myDoubleAniamtion添加到myStoryboard的Children中去.最后就可以通过调用Storyboard的Begin(FrameworkElement)方法来开始我们的动画.

Begin方法的另一个重载形式是public void Begin (FrameworkContentElement containingObject,bool isControllable),第二个参数表明我们的storyboard是否是可控的,如果可控的话,我们可以像控制播放器一样控制来控制storyboard,关于控制Storyboard请参考Storyboard类中的Pause,Seek等方法.

至此也许我们会认为这些知识足以应付简单的动画了,现在让我们一起设计一个简单的动画,也许会发现些问题.

假设我们的界面中存在一个Button对象button1,我们设计一个简单的动画让它在窗口中的x坐标从0连续变化到100,然后在从100变化到0,如此重复.也许我们会编写如下的代码:

            this.button1.Name = "button1";this.Name = "window1";NameScope.SetNameScope(this, new NameScope());this.RegisterName(this.button1.Name, this.button1);DoubleAnimation xAnimation = new DoubleAnimation();xAnimation.From = 0;xAnimation.To = 100;xAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));Storyboard story = new Storyboard();story.AutoReverse = true;story.RepeatBehavior = RepeatBehavior.Forever;story.Children.Add(xAnimation);Storyboard.SetTargetName(xAnimation, this.button1.Name);Storyboard.SetTargetProperty(xAnimation, ???);

但当我们编写到Storyboard.SetTargetProperty(xAnimation, ???);时发现似乎不知道将我们的xAniamtion关联到哪个属性.似乎Button中没有用来控制X坐标的DependencyProperty.但通过研究后发现(你可以通过ExpressionBlend自动生成的XAML代码来发现这些信息),如果我们将button1的RenderTransform设置为TranslateTransform,然后可以通过TranslateTransform的XProperty属性来更改button1的X坐标.注意到,我们并不是像以前一样直接关联到Button的某个属性(比如先前的WidthProperty),而是通过其RenderTransformProperty属性的XProperty来间接关联的,这中方式叫做"属性链"(PropertyChain).
参考下面的代码:

            DependencyProperty[] propertyChain = new DependencyProperty[]{Button.RenderTransformProperty,TranslateTransform.XProperty};Storyboard.SetTargetProperty(xAnimation, new PropertyPath("(0).(1)", propertyChain));

为了构造PropertyChain,我们先定义一个DependencyProperty的数组,注意数组的元素是怎么来的,它按照属性链的"链条"关系依次书写,直到到达我们最终要修改的属性,(由于我们是通过将RenderTransformProperty设置为TranslateTransform类型,所以第二个元素是TranslateTransform.XProperty),简单地说就是(类型1.属性1,类型2.属性2,....类型n.属性n),其中类型i是属性i-1的类型或可以与之转换的类型.
这样我们的代码就演化如下:

            this.button1.RenderTransform = new TranslateTransform();this.button1.Name = "button1";this.Name = "window1";NameScope.SetNameScope(this, new NameScope());this.RegisterName(this.button1.Name, this.button1);DoubleAnimation xAnimation = new DoubleAnimation();xAnimation.From = 0;xAnimation.To = 100;xAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));DependencyProperty[] propertyChain = new DependencyProperty[]{Button.RenderTransformProperty,TranslateTransform.XProperty};Storyboard story = new Storyboard();story.AutoReverse = true;story.RepeatBehavior = RepeatBehavior.Forever;story.Children.Add(xAnimation);Storyboard.SetTargetName(xAnimation, this.button1.Name);Storyboard.SetTargetProperty(xAnimation, new PropertyPath("(0).(1)", propertyChain));story.Begin(this);

注意:如果你收到关于PropertyChain的运行时错误或动画没有效果,那么你应该初始化button的RenderTransform属性,所以我们添加了this.button1.RenderTransform = new TranslateTransform();语句.

=======================================================================================================================

)wpf动画——new PropertyPath属性链

 

在wpf中我们常用storyboard故事板装载很多的动画处理Animation,我们需要用Storyboard.SetTarget设置操作的对象,需要用Storyboard.SetTargetProperty设置操作对象的操作属性PropertyPath,本例将说明一种操作属性PropertyPath的便利方法:

1.新建一个wpf应用程序,简单修改一下xaml展示如下:

<Window x:Class="WpfApplication48.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="MainWindow" Height="350" Width="525"><Grid><Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" /></Grid>
</Window>

2.后台cs修改如下(效果:点击button,button的横坐标x由12到300,播放过程动画):

    /// <summary>/// MainWindow.xaml 的交互逻辑/// </summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();}private void button1_Click(object sender, RoutedEventArgs e){this.button1.RenderTransform = new TranslateTransform();Storyboard sb = new Storyboard();DoubleAnimation da = new DoubleAnimation();da.From = 12;da.To = 300;da.Duration = TimeSpan.FromSeconds(3);sb.Children.Add(da);DependencyProperty[] propertyChain = new DependencyProperty[]{Button.RenderTransformProperty,TranslateTransform.XProperty};Storyboard.SetTarget(da, this.button1);Storyboard.SetTargetProperty(da, new PropertyPath("(0).(1)", propertyChain));sb.Completed += new EventHandler((object sender1, EventArgs e1) => { MessageBox.Show("completed"); });sb.Begin();}}

一般我们在写到Storyboard.SetTargetProperty时遇到new PropertyPath,

如果是简单的属性,例如Button.WidthProperty,我们可以直接new PropertyPath(Button.WidthProperty)达到目的,
但如果你发现你需要操作到的属性无法在Button中直接'.'出来,就需要用到上例用到的属性链方法:

首先定义一个属性链:

            DependencyProperty[] propertyChain = new DependencyProperty[]{Button.RenderTransformProperty,TranslateTransform.XProperty};

属性链的写法,定义一个DependencyProperty属性的数组,该数组中的元素均是Property属性,且按照从属关系先后排列,例如上例中,我们需要先将button的RenderTransform设置为TranslateTransform,然后通过TranslateTransform的XProperty来更改button的x坐标,

当然,别忘了初始化button的RenderTransform属性= new TranslateTransform(),否则动画将没有效果。

 

以上未经博主同意转载,敬请原谅。

转载于:https://www.cnblogs.com/Owen-ET/p/5981660.html

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

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

相关文章

python无法使用1号gpu_详解tensorflow2.x版本无法调用gpu的一种解决方法

最近学校给了一个服务器账号用来训练神经网络使用&#xff0c;服务器本身配置是十路titan V&#xff0c;然后在上面装了tensorflow2.2&#xff0c;对应的python版本是3.6.2&#xff0c;装好之后用tf.test.is_gpu_available()查看是否能调用gpu&#xff0c;结果返回结果是false&…

使用Chrome Dev Tools, deb.js调试Javascript小技巧

本文讲介绍一些基于 Chrome Dev Tools 的实用的客户端Javascript 调试小技巧。我将重点关注那些无从下手&#xff0c;不知道该在哪儿添加断点的情景。 首先看下本文主题&#xff1a; 找出哪段代码正在修改了页面找出谁发送了某个ajax请求在抛出异常时触发断点条件断点事件断点…

jenkins Auth fail验证失败

重新设置密码转载于:https://www.cnblogs.com/cocoat/p/5982931.html

CSS3 Perspective

一 、在元素的父元素上使用 在父元素上使用Perspective属性可以使用透视投影视图&#xff0c;在父元素上加上&#xff1a; perspective:400px 表示相机距离屏幕位置为400px。默认相机对准父元素的中心&#xff0c;要重设相机的焦点可以使用&#xff1a; perspective-origin…

在ASP.NET Core使用Middleware模拟Custom Error Page功能

一、使用场景 在传统的ASP.NET MVC中,我们可以使用HandleErrorAttribute特性来具体指定如何处理Action抛出的异常.只要某个Action设置了HandleErrorAttribute特性,那么默认的,当这个Action抛出了异常时MVC将会显示Error视图,该视图位于~/Views/Shared目录下。 自定义错误页面的…

状态模式案例分析

需求 初始状态下&#xff0c;【暂停按钮】不可点&#xff0c;所有数轴可调: 点击【动态波】后&#xff0c;【暂停按钮】可点&#xff0c;所有数轴可调&#xff1a; 点击【暂停按钮】后&#xff0c;“暂停”变为“播放”&#xff0c;所有数轴不可调&#xff1a; 分析需求 上面…

Linux系统IP地址

1、IP地址概述 2、配置IP地址 查看IP地址 在网卡上绑定一个IP地址 同一张网卡上绑定多个IP 绑定一块网卡设备 修改或删除IP地址 IP地址概述 这里不多赘述&#xff0c;参考《计算机网络》课程。 配置IP地址 [rootweekend110 ~]# ifconfigeth0    Link encap:Ethernet HWadd…

qwidget多个窗口同步_Linux命令screen—终端切换,工作环境保存,画面同步,防断网...

Screen基础Screen是一款由GNU计划开发的用于命令行终端切换的自由软件。用户可以通过该软件同时连接多个本地或远程的命令行会话&#xff0c;并在其间自由切换。GNU Screen可以看作是窗口管理器的命令行界面版本。它提供了统一的管理多个会话的界面和相应的功能。创建一个新的窗…

Snap svg:路径变换和相交计算

Snap.svg对原生的svg进行了封装&#xff0c;为svg的创建、操作提供了便捷的方法&#xff0c;但是官网的文档对一些概念没有解释&#xff0c;难免会造成困扰。比如说路径的旋转&#xff0c;就存在变换后得不到路径交点的问题。 用普通的变换得不到路径的相交点 Snap.svg提供了…

Linux文件基本操作

使用declare命令创建一个变量名为 tmp 的变量&#xff1a; 使用号赋值运算符为变量 tmp 赋值为 dunzhu&#xff1a; 读取变量的值&#xff0c;使用echo命令和$符号&#xff08;$符号用于表示引用一个变量的值&#xff0c;初学者经常会忘记输入&#xff09; 在dunzhu家目录创建一…

Snap svg 主要对象

对象概述Elementsvg规定的元素&#xff0c;提供修改属性、绑定事件、操作数据、操作层级关系、动画等方面的方法&#xff0c;类似jquery选取的元素Fragment虚拟节点&#xff0c;其用处是可以用js创建多个元素&#xff0c;添加到Fragment&#xff0c;不会影响到实际的DOM&#x…

初中位似图形作图_[如何画位似图形] 位似图形的画法及步骤

如何画位似图形位似变换是新课程标准中涉及的一个重要知识点&#xff0c;它是图形变换的一种&#xff0c;实际上它是相似变换的一种特殊情形&#xff0c;存在位似中心———即对应顶点连线的交点&#xff0e;其位似比就是相似比&#xff0e;作为一个新的知识点&#xff0c;越来…

DES 加密 解密

EncryptUtil feiyangklDES 一行代码完成DES加密&#xff0c;加密模式 DES CBC DEMO GIF DEMO 简介 最近项目中用到DES加密&#xff0c;在这里整理成篇&#xff0c;供大家参考阅读&#xff0c;在使用该demo过程中&#xff0c;你可能会遇到一些问题&#xff0c;首先你需要看一下…

bootstrap带有下拉按钮的输入框_关于bootstrap--表单(下拉select、输入框input、文本域textare复选框checkbox和单选按钮radio)...

html 里面的 role 本质上是增强语义性&#xff0c;当现有的HTML标签不能充分表达语义性的时候&#xff0c;就可以借助role来说明。通常这种情况出现在一些自定义的组件上&#xff0c;这样可增强组件的可访问性、可用性和可交互性。role的作用是描述一个非标准的tag的实际作用。…

CSS3 线性渐变背景的过渡效果

对于background-color&#xff0c;可以直接transition: background-color 2s就能实现过渡效果&#xff0c;但对于background:-webkit-radial-gradient(circle,#ffc71d 0,rgba(168,117,14,.5) 130%);就无能为力了。对于这种复杂的背景&#xff0c;只能给opacity添加过渡效果了&a…

markdown绘图插件----mermaid简介

作者&#xff1a;黄永刚 mermaid简介 当撰写文档的时候&#xff0c;对于流程图的生成大多使用Visio等繁重的工具&#xff0c;没有一种轻便的工具能够画图从而简化文档的编写&#xff0c;就像markdown那样。 mermaid解决这个痛点&#xff0c;这是一个类似markdown语法的脚本语言…

华为三层交换机路由配置案例_华为三层交换机配置实例

1华为三层交换机配置实例一例服务器1双网卡&#xff0c;内网IP:&#xff0c;其它计算机通过其代理上网PORT1属于VLAN1PORT2属于VLAN2PORT3属于VLAN3VLAN1的机器可以正常上网配置VLAN2的计算机的网关为&#xff1a;配置VLAN3的计算机的网关为&#xff1a;即可实现VLAN间互联如果…

大学只待成追忆,只是工作已半年,2016再见

时光匆匆&#xff0c;真的不知不觉&#xff0c;已经毕业半年。这一年发生了好多事&#xff0c;回望简直难以相信。 再见广州&#xff0c;你好厦门 广深工作好找&#xff0c;但心就是想离开&#xff0c;当时想的是&#xff0c;找一个地方&#xff0c;让一切重新开始。来到厦门…

centos7挂载nas存储_CentOS7搭建NAS文件共享存储

概述&#xff1a;NFS是一种基于TCP/IP传输的网络文件系统协议&#xff0c;最初由SUN公司开发。通过NFS协议&#xff0c;客户机可以像访问本地目录一样访问远程服务器中的共享资源。NFS得到了如NAS等网络存储的设备极好支持。也是LVS共享存储的首选。环境&#xff1a;CentOS 7.8…

【移动端html5】 android video播放进度精确控制

android上视频播放存在的问题 在PC上播放html5视频&#xff0c;设置video.currentTime5,视频将跳到5s的位置&#xff0c;并且显示出第5s的画面。在安卓下&#xff0c;却存在下面两个问题&#xff1a; 在安卓上&#xff0c;为了省电&#xff0c;在暂停的时候&#xff0c;改变视…