WPF之小动画二
上一篇文章简单介绍了动画的定义方法和一些控制动画的方法,并没有涉及复杂属性的动画处理方式,本文将继续动画的其它方面的使用。
写在前面(对于一些动画操作时候的建议):
1.如果希望某个元素从显示到消失,或者从消失到显示,使用Visibility属性是无效的,因为此属性没有一个动画的过程,所以使用Opacity控制透明度进行操作;
2.如果要修改元素的位置则可以使用Canvas.Left或者Canvas.Top设置是RenderTransform(下文会涉及);
3.可以使用ColorAnimation修改元素的Brush,如果是比较复杂的aBrush,则可以使用DoubleAnimation来修改OffSet偏移量。
动画和Transforms:
Transforms可以对元素进行水平和垂直移动、可以使元素旋转、也可以使元素放大缩小以及进行使元素扭曲,通常在动画中会修改各种Transform的属性以达到动画的效果。
<Window x:Class="WpfApplication3.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="HorizontalAlignment" Value="Center"></Setter>
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"></Setter>
<Setter Property="Padding" Value="20,15"></Setter>
<Setter Property="Margin" Value="2"></Setter>
<Setter Property="RenderTransform">
<Setter.Value>
<RotateTransform></RotateTransform>
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Button.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.Angle"
To="360" Duration="0:0:0.8" RepeatBehavior="Forever"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Button.MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.Angle"
Duration="0:0:0.2"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel Margin="5">
<Button>One</Button>
<Button>Two</Button>
<Button>Three</Button>
<Button>Four</Button>
<TextBlock Name="lbl" Margin="5"></TextBlock>
</StackPanel>
</Window>
效果图为窗体上有四个按钮,鼠标悬浮到按钮上,按钮则进行360度的持续旋转,当鼠标离开,则恢复原状。
代码解析:上述代码的语法在上一篇博客中已经介绍过,通过Style和Trigger以及Animation进行操作,唯一区别就是在上述代码中使用了RenderTransform。可以看到在样式中给Button添加了RenderTransform属性,此处使用的是RotateTransform,也就是旋转变换。在MouseEnter时候开始执行动画,动画的属性为RenderTransform.Angle即旋转的角度,To就是360度,并且动画吃持续性的。在MouseLeave时候开始执行恢复原状的动画,如果From和To都不设置则将To默认为原有的值。(之所以可以直接使用RenderTransform.Angle是因为当前我们的RenderTransform只有一个变换对象,所以可以直接使用的,如果有多个变换对象,则要看下文喽)
Tips:LayoutTransform和RenderTransform的区别
与 RenderTransform相比, LayoutTransform 将影响布局的结果。 设置转换提供缩放和旋转的强大功能。 但是, LayoutTransform 忽略 TranslateTransform 操作。 这是因为, FrameworkElement 的子元素的布局系统行为自动更正对缩放的或旋转的元素的位置的所有偏移量父元素的布局和坐标系中。 LayoutTransform 可能导致应用程序性能变差,如果调用它在不需要布局系统执行全面处理过程的方案。 将 LayoutTransform 于 Panel时的 Children 集合,它将触发布局系统新通过和强制屏幕上的所有对象。重新度量和重新排列。 如果要更新完整的应用程序 用户界面 (UI),此功能可能完全符合您的需要。 但是,因此,如果不需要完整布局处理过程,请使用 RenderTransform 属性,不会调用布局系统,并且,通常是此方案的更好的选择。 |
理论说多了都是泪,看看LayoutTransform的例子:
<Style TargetType="{x:Type Button}">
<Setter Property="HorizontalAlignment" Value="Center"></Setter>
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"></Setter>
<Setter Property="Padding" Value="20,15"></Setter>
<Setter Property="Margin" Value="2"></Setter>
<Setter Property="LayoutTransform">
<Setter.Value>
<RotateTransform></RotateTransform>
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Button.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="LayoutTransform.Angle"
To="360" Duration="0:0:0.8" RepeatBehavior="Forever"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Button.MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="LayoutTransform.Angle"
Duration="0:0:0.2"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
如你所见,没有怎么改动,只是把RenderTransform的地方都改为了LayoutTransform(话说楼主也是因为Property写的是LayoutTransform,而在动画中使用的是RenderTransform,却一直报错)。运行程序,你会发现按钮在旋转的时候整个布局都是弹跳(比喻),其实就是动态更改布局。
多个Transform(TransformGroup):
顾名思义,多个Transform,也就意味着可以同时向元素应用多个Transform,也可以在动画中对其,进行修改。下面的例子为,默认情况下Image倾斜角度为50,并且缩放了0.5倍,同时Image的Opacity透明度为0.5,在窗口进行最大化的时候使Image角度为0,然后大小正常,透明度为1。
<Image Height="300" Width="300" Source="Desert.jpg" Opacity="0.5" x:Name="imgTransform">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="0.5" ScaleY="0.5"></ScaleTransform>
<RotateTransform Angle="50"></RotateTransform>
</TransformGroup>
</Image.RenderTransform>
</Image>
动画资源
<Window.Resources>
<Storyboard x:Key="sbTransform">
<DoubleAnimation Storyboard.TargetName="imgTransform" Storyboard.TargetProperty="RenderTransform.Children[0].ScaleX" To="1" Duration="0:0:1"></DoubleAnimation>
<DoubleAnimation Storyboard.TargetName="imgTransform" Storyboard.TargetProperty="RenderTransform.Children[0].ScaleY" To="1" Duration="0:0:1"></DoubleAnimation>
<DoubleAnimation Storyboard.TargetName="imgTransform" Storyboard.TargetProperty="RenderTransform.Children[1].Angle" To="0" Duration="0:0:1"></DoubleAnimation>
<DoubleAnimation Storyboard.TargetName="imgTransform" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:1"></DoubleAnimation>
</Storyboard>
</Window.Resources>
解释:在Image中主要是对其RenderTransform使用了TransformGroup,表示可以放置多个Transform,在此是一个缩放的ScaleTransform和一个旋转的RotateTransform。在动画中使用了四个DoubleAnimation,前三个为Transform。在TargetProperty中使用的属性是不是觉得很奇怪,那你还记不记得我们第一个例子中是直接使用RenderTransform.属性的呢,区别就是第一个例子我们只有一个Transform,而这里我们有两个(是一个集合哦),所以我们需要通过RenderTransform的Children属性根据索引得到对应的Transform。在这里0代表的就是ScaleTransform,1就是RotateTransform,所以可以分别设置它们的属性,最后一个Animation没什么说的,就是修改透明度。
开始动画:
private void Window_SizeChanged_1(object sender, SizeChangedEventArgs e)
{
if (WindowState== System.Windows.WindowState.Maximized)
{
Storyboard storyboard = this.Resources["sbTransform"] as Storyboard;
storyboard.Begin();
}
}
在窗口的SizeChange中,判断如果为最大化,则开始动画。
动画和颜色(Brush):
颜色:
<Rectangle Name="rectTest" Fill="Green" Height="100" Width="100" >
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown">
<BeginStoryboard>
<Storyboard>
<ColorAnimation To="Red" Storyboard.TargetProperty="Fill.Color" Duration="0:0:1"></ColorAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
一个Rectangle矩形,默认为绿色,点击之后变为红色。在这里使用的是ColorAnimation,表示颜色动画,这个不是重点,重点是Property的设置,由于颜色(不管是Rectangle的Fill还是其它元素的Background类型都是Brush)的类型都是Brush,而Brush是无法进行设置的,所以需要给其Color进行设置,也就看到了上述的语法。
Brush:
上述例子修改的是某一个元素的颜色,现在开始试着修改Brush这样的类型。
动画修改偏移量:
<Rectangle Name="rectTest" Height="100" Width="100" >
<Rectangle.Fill>
<LinearGradientBrush>
<GradientStop Offset="0" Color="Red"></GradientStop>
<GradientStop Offset="1" Color="Green"></GradientStop>
</LinearGradientBrush>
</Rectangle.Fill>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation To="0.2" Storyboard.TargetProperty="Fill.GradientStops[0].Offset" Duration="0:0:1"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
此例子关键点在于Property,Fill.GradientStops表示画刷的整个渐变点的集合,然后通过索引确定某一个渐变项,然后修改偏移量。
动画修改渐变项的颜色:
<Rectangle Name="rectTest" Height="100" Width="100" >
<Rectangle.Fill>
<LinearGradientBrush>
<GradientStop Offset="0" Color="Red"></GradientStop>
<GradientStop Offset="1" Color="Green"></GradientStop>
</LinearGradientBrush>
</Rectangle.Fill>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown">
<BeginStoryboard>
<Storyboard>
<ColorAnimation To="Yellow" Storyboard.TargetProperty="Fill.GradientStops[0].Color" Duration="0:0:1"></ColorAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
此例子关键点和上述基本一致,唯一区别是使用了ColorAnimation,修改的是Color属性。
动画修改画刷的属性和渐变项的颜色:
<Rectangle Name="rectTest" Height="100" Width="100" >
<Rectangle.Fill>
<RadialGradientBrush GradientOrigin="0.5,0.5">
<GradientStop Offset="0" Color="Red"></GradientStop>
<GradientStop Offset="1" Color="Green"></GradientStop>
</RadialGradientBrush>
</Rectangle.Fill>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown">
<BeginStoryboard>
<Storyboard>
<PointAnimation To="0.7,0.5" Storyboard.TargetProperty="Fill.GradientOrigin" Duration="0:0:1"></PointAnimation>
<ColorAnimation To="Yellow" Storyboard.TargetProperty="Fill.GradientStops[0].Color" Duration="0:0:1"></ColorAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
此例子关键点在第一个动画,Property修改的是Brush的Gradientorigin属性而并非见渐变项的,从上述各种代码可以看到,如果元素的颜色属性就是一个Bursh,那么可以使用“颜色属性.Brush的属性"进行访问。
动画和着色器(BlurEffect):
<Button Content="A Button">
<Button.Effect>
<BlurEffect Radius="10"></BlurEffect>
</Button.Effect>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Effect.Radius" To="0" Duration="0:0:0.4"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Button.MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Effect.Radius" To="10" Duration="0:0:0.2"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Button.Triggers>
</Button>
一个Button,添加了BlurEffect用于模糊,默认模糊为10像素,当鼠标悬浮时候变为正常,鼠标离开变为10想速度模糊,没有难点,和之前的大致一样,例子旨在说明动画可以应用到大部分你想改变的属性上。
关键帧动画(本来是蛮不错的东西,不过本人之前的Silverlight中已经有提到,大家可以移步到此,戳我):
轨迹动画(Path-Animation):
轨迹动画,顾名思义,根据某一段轨迹进行运动的过程,当然也就少不了三元素,要运动的Element,轨迹Path,动画。
<Window.Resources>
<PathGeometry x:Key="path">
<PathFigure IsClosed="True">
<ArcSegment Point="100,200" Size="15,10" SweepDirection="Clockwise"></ArcSegment>
<ArcSegment Point="400,50" Size="5,5" ></ArcSegment>
</PathFigure>
</PathGeometry>
<Storyboard x:Key="sbTest">
<DoubleAnimationUsingPath
Storyboard.TargetName="image"
Storyboard.TargetProperty="(Canvas.Left)"
PathGeometry="{StaticResource path}"
Duration="0:0:5"
RepeatBehavior="Forever"
Source="X"/>
<DoubleAnimationUsingPath
Storyboard.TargetName="image"
Storyboard.TargetProperty="(Canvas.Top)"
PathGeometry="{StaticResource path}"
Duration="0:0:5"
RepeatBehavior="Forever"
Source="Y"/>
</Storyboard>
</Window.Resources>
上述代码中放置了一个Path,表示运动的轨迹(轨迹的语法有点DT,所以大家还是去找MSDN吧)。一个动画,动画的类型是前所没有使用过的DoubleAnimationUsingPath,表示使用Path执行的Double动画。TargetName下文会出现就是一图片(其实是使用DrawingImage绘制的),Property又好奇怪,其实这个就是附加属性的语法(关于这个大家再移步一下,戳我)。接下来重要的出现了,PathGeometry和Source,没错前者就是要运动的轨迹,果断把我们的Path丢给它;Source又是嘛意思呢,根据MS的解释就是在运动过程中的输出,说白了就是这个值到底是X还是Y还是Angle,因为Path是一系列de坐标组成的,所以你懂得。在两个动画中分别设置Canvas.Left和Canvas.Top,Left当然应该使用X,而Top也顺其自然的使用Y了。
看到了吧,小图片根据这个轨迹在蹭蹭蹭的跑呢。
好了,此次介绍就到这里了,下一篇会有亮瞎眼睛的东西哦,敬请期待。
WPF之小动画二的更多相关文章
- jquery实现一些小动画二
jquery实现一些小动画二 jquery实现拖拽功能 <!DOCTYPE html> <html lang="en"> <head> < ...
- WPF之小动画三
如果前两篇的博客太为普通,那么接下来的内容将让你动画实在是太厉害了.本文将会介绍两个关于纯手工实现动画的形式,当然动画效果就不用我多说了. 基于帧的动画: 此处的帧并不是之前介绍的Animation这 ...
- WPF之小动画一
定义动画: 直接使用Element进行BeginAnimation DoubleAnimation animation = new DoubleAnimation(); animation.By = ...
- WPF入门教程系列(二) 深入剖析WPF Binding的使用方法
WPF入门教程系列(二) 深入剖析WPF Binding的使用方法 同一个对象(特指System.Windows.DependencyObject的子类)的同一种属性(特指DependencyProp ...
- 如何制作网页小动画?——gif or png
一.场景与动画 为了拉动网站氛围,或者吸引用户浏览焦点,需要使用一些小动画.这种动画不是(gif)单纯的重复,而是需要需要一些控制和交互,比如在动画完成后打开一个对话框.动画有几个基本要素(时间控制, ...
- WPF学习拾遗(二)TextBlock换行
原文:WPF学习拾遗(二)TextBlock换行 下午在帮组里的同事解决一个小问题,为了以后方便,把就把它收集一下吧. 新建一个TextBlock作为最基础的一个控件,他所携带的功能相对于其他的控件要 ...
- WPF命中测试示例(二)——几何区域命中测试
原文:WPF命中测试示例(二)--几何区域命中测试 接续上次的命中测试,这次来做几何区域测试示例. 示例 首先新建一个WPF项目,在主界面中拖入一个按钮控件,并修改代码中的以下高亮位置: 当前设计视图 ...
- 【WPF学习笔记】[转]周银辉之WPF中的动画 && 晓风影天之wpf动画——new PropertyPath属性链
(一)WPF中的动画 动画无疑是WPF中最吸引人的特色之一,其可以像Flash一样平滑地播放并与程序逻辑进行很好的交互.这里我们讨论一下故事板. 在WPF中我们采用Storyboard(故事板)的方式 ...
- WPF 有趣的动画效果
WPF 有趣的动画效果 这一次我要呈上一个简单的文章,关于给你的WPF apps加入美丽的光线动画,可是我对动画这东西可能有点入迷了. 实际上.我对动画如此的入迷,以至 ...
随机推荐
- [easyui] datebox源码阅读. 批注
jquery.datebox.js 文件. (function($){ /** * create date box */ function createBox(target){ var state = ...
- Bugzilla+MySql+IIS+ActivePerl搭建指南
头在忙着他的技术研究,对团队建设.测试管理.流程规范都不怎么理会,眼见着产品进入后期整合阶段,在测试过错中出现很多Bug,单靠着我一个人用txt来收集整理bug需求,然后整理成word,放在svn上面 ...
- json-lib-2.4.jar Bug,json字符串中value为"[value]"结构时,解析为数组,不会解析成字符串
使用json-lib.jar 2.4进行json字符串转换为对象时发现一个bug.贴下测试代码: <dependency> <groupId>net.sf.json-lib&l ...
- js判断IE6(推荐方法一)
不得不使用判断的方法 //方法1:推荐 if ( /MSIE 6/.test(navigator.userAgent)){ } //方法2: if ( navigator.appVersion.ind ...
- 伪元素content的应用
日常开发中,我们常用:before,:after来实现一些效果,比如 – 边框 – 图标 此时的content中只是为了伪元素能渲染出来而声明 1 2 3 div:before{ content: & ...
- jQuery 图片轮播的代码分离
以前遇到过jQuery实现列表自动滚动,这次的图片轮播在原理上与之相同,只有一些细微的差别,就是需要在图片的右下角显示当前图片的序号. html代码,以及对应的css代码: <div id=&q ...
- php入门常量
常量像变量一样,用于临时存储一个值,但是常量在许多方面与变量不同. 常量:1.是在程序执行期间无法改变数据,常量的作用域是全局的.2.常量的命名与与变量相似,只是不带美元符号“$”.一个有效的常量名由 ...
- Failed to execute command: ""C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\ResGen.exe" 的一个解决办法
最近在做wpf项目,期间下了一些源码参考,但是在build时经常遇到下面这种bug: Error 2 Failed to execute command: ""C:\Program ...
- mac上xampp配置
sudo su /Applications/XAMPP/xamppfiles/xampp security
- JAVA中的各种 哈希码(HashCode) 与 equals方法在HIBERNATE的实际应用[转载]
1.什么是哈希码(HashCode) 在Java中,哈希码代表对象的特征.例如对象 Java代码 String str1 = “aa”, str1.hashCode= 3104 String str2 ...