wpf学习之动画.docx
- 文档编号:4711501
- 上传时间:2022-12-07
- 格式:DOCX
- 页数:10
- 大小:21.01KB
wpf学习之动画.docx
《wpf学习之动画.docx》由会员分享,可在线阅读,更多相关《wpf学习之动画.docx(10页珍藏版)》请在冰豆网上搜索。
wpf学习之动画
WPF学习之动画
WPF学习之动画
Admin
2010年6月19日名人名言:
只有劳动才能使人变得幸福,使他的心灵变得开朗、和谐、心满意足。
——别林斯基WPF学习之动画对于windowsForm程序员来说,没有动画的概念,如果我们要实现一个动态的效果,就是配置一个定时器,然后根据定时器的频率来循环的调用回调函数在一段时间
不断的更新目标函数的属性来实现动画效果。
用定时器来模拟动画
在界面上面放一个圆<Canvas><EllipseCanvas.Left="24"Canvas.Top="68"Margin="39,39,0,0"Stroke="Black"Height="38"HorizontalAlignment="Left"
VerticalAlignment="Top"Width="42"Fill="Yellow"Name="yuan"/><ButtonCanvas.Left="38"Canvas.Top="213"Height="23"Name="button1"Width="75"Click="button1_Click">开始</Button></Canvas>当点击按钮是创建一个定时器执行DispatcherTimertimer;inti=0;
privatevoidbutton1_Click(objectsender,RoutedEventArgse){timer=newDispatcherTimer(DispatcherPriority.Normal);timer.Tick+=newEventHandler(timer_Tick);timer.Interval=TimeSpan.FromMilliseconds(20);timer.Start();}这里定时器对象是在System.Windows.Threading命名空间下面,需要引入System.Windows.Threading
voidtimer_Tick(objectsender,EventArgse){//thrownewNotImplementedException();move(newPoint(0,1));}publicvoidmove(Pointp){//这里我们希望圆每次移动ppointPointpt=newPoint(Canvas.GetTop(yuan),Canvas.GetLeft(yuan));//得到当前对象的位置//改变位置Canvas.SetTop(yuan,pt.X+p.X);Canvas.SetLeft(yuan,pt.Y+p.Y);i++;if(i>=100){timer.Stop();}}这里我们让圆对象向右移动,执行100次之后停止。
这样就模拟出一个基于定时器的动画。
当然你也可以使用
System.Timers.TimerSystem.Timers.Timertm=newSystem.Timers.Timer();tm.Interval=20;tm.Elapsed+=newSystem.Timers.ElapsedEventHandler(tm_Elapsed);tm.Start();或者是System.Threading.Timer但是
System.Threading.Timer是一个简单的轻量计时器,它使用回调方法并由线程池线程提供服务。
不建议将其用于Windows窗体,因为其回调不在用户界面线程上进行。
System.Windows.Forms.Timer是用于Windows窗体的更佳选择。
要获取基于服务器的计时器功能,可以考虑使用System.Timers.Timer,它可以引发事件并具有其他功能。
【MSDN】
windows程序员可能很熟悉这种实现方式,但是用定时器来实现动画并不是推荐的办法。
定时器无法根据显示器的垂直刷新率进行同步,
也不能与WPF的渲染引擎同步【WPF揭秘】
用Rendering事件来实现基于帧的动画
在WPF中,可以通过System.Windows.Media.CompositionTarget的Rendering事件来实现基于帧的动画,它和Timer不同的就是
它不是在定制的时间区间里引发的,而是在布局后和渲染前的每一帧引发一次。
CompositionTarget是一个类,表示正在其上绘制您的应用程序的显示图面。
【MSDN】CompositionTarget.Rendering+=newEventHandler(CompositionTarget_Rendering);voidCompositionTarget_Rendering(objectsender,EventArgse){//thrownewNotImplementedException();move(newPoint(0,1));}
publicvoidmove(Pointp){//这里我们希望圆每次移动ppointPointpt=newPoint(Canvas.GetTop(yuan),Canvas.GetLeft(yuan));//得到当前对象的位置//改变位置Canvas.SetTop(yuan,pt.X+p.X);Canvas.SetLeft(yuan,pt.Y+p.Y);}由于Rendering事件和界面的刷新频率有关,所有我们不能够控制它的执行。
但处理程序是在UI线程中调用的,不用担心线程通信的问题。
WPF动画
虽然使用上面的两种方法也是实现动画的一个办法,在WPF中提供了动画类,让动画成为更加简单和说明性的流程。
在
System.Windows.Media.Animation命名空间中定义了许多类,能够很方便的描述动画。
在WPF中实现一个动画需要三个必备的条件:
动画对象、故事板、事件触发
一个最简单的WPF动画
在一个按钮下面写上如下代码//1.创建动画对象DoubleAnimationdoubleAnimation=newDoubleAnimation();doubleAnimation.From=10;//设置开始值doubleAnimation.To=100;//设置结束值doubleAnimation.Duration=newDuration(TimeSpan.FromSeconds(5));//动画运行时间doubleAnimation.AutoReverse=true;//设置动画播放完后反向在播放doubleAnimation.RepeatBehavior=RepeatBehavior.Forever;//设置为循环播放//2.创建故事板并把动画对象加入到该故事板中Storyboardstoryboard=newStoryboard();storyboard.Children.Add(doubleAnimation);//3.指定要执行该故事板的对象Storyboard.SetTarget(doubleAnimation,yuan);//指定要执行动画的对象。
//4.指定要进行动画处理的属性Storyboard.SetTargetProperty(doubleAnimation,newPropertyPath("(Canvas.Top)"));storyboard.Begin();//开始动画
在上面定义了一个DoubleAnimation类型的动画,然后把动画加入了故事板storyboard,最后设置执行动画的对象和改变的属性。
当然Storyboard还提供了Stop(停止)、Pause(暂停)、Resume(继续)方法来控制动画
动画类型
动画类型总体上分为两类From/To/By动画和关键帧动画
From/To/By动画:
在起始值From和结束值To之间处理动画,之间的时间由Duration属性控制,若要指定相对于起始值的结束值何以设定By属性
关键帧动画:
在使用关键帧对象指定的一系列的值之间播放动画。
属性类型对应的基本(From/To/By)动画对应的关键帧动画ColorColorAnimationColorAnimationUsingKeyFramesDoubleDoubleAnimationDoubleAnimationUsingKeyFramesPointPointAnimationPointAnimationUsingKeyFramesObject无ObjectAnimationUsingKeyFramesColorAnimation在指定的Duration内使用线性内插对两个目标值之间的Color属性值进行动画处理。
DoubleAnimation在指定的Duration内使用线性内插对两个目标值之间的Double属性值进行动画处理。
PointAnimation在指定的Duration内使用线性内插对两个目标值之间的Point属性值进行动画处理。
动画是时间线
所有的动画均继承自Timeline对象,因此所有的动画都是专用类型的时间线。
常用的属性有
Duration表示时间线完成一次重复
AutoReverse指定时间线在到达其Duration的终点后是否倒退。
如果将此动画属性设置为true
RepeatBehavior指定时间线的播放次数
BeginTime设定动画的开始时间
SpeedRatio设定动画的速率
FillBehavior设定动画结束后的行为,有两个值HoldEnd保持当前值,Stop结束后变为初始值。
故事板
故事板对象中提供了一系列的API用于控制对象的播放。
开始、暂停、继续、停止等。
对于故事板提供了TargetName和TargetProperty的附加属性,通过在动画上设置这些属性。
告诉我们动画对那些内容进行动画处理。
//3.指定要执行该故事板的对象Storyboard.SetTarget(doubleAnimation,yuan);//指定要执行动画的对象。
//4.指定要进行动画处理的属性Storyboard.SetTargetProperty(doubleAnimation,newPropertyPath("(Canvas.Top)"));在例子中的第三步和第四步就是完成了对这两个值的设定。
WPF中能够很方便的创建动画,在上面提到的三种创建动画的方式在园子里深蓝的系列教程C#开发WPF/Silverlight动画及游戏系列教程(GameTutorial)
中对于三种动画适用的地方也说的比较详细,而我开始看WPF也是看到深蓝的教程开始的。
在WPF揭秘这本书里也是介绍了三种动画的方式。
主要还是第三种。
关键帧动画
关键帧动画与From/To/By动画类似,关键帧动画以动画的形式显示了目标属性的值。
它通过其Duration创建其目标之间的过渡。
但是,From/To/By动画创建两个值之间的过渡,而点歌关键帧动画可以创建任意数量的目标值之间的过渡。
关键帧动画需要创建关键帧对象,并添加到动画的KeyFrames属性。
动画运行是,将在指定的帧之间过渡
一个简单的关键帧动画
<Canvas><EllipseCanvas.Left="38"Canvas.Top="40"Height="49"Name="ellipse1"Stroke="Black"Width="52"Fill="Turquoise"/><ButtonCanvas.Left="92"Canvas.Top="233"Height="23"Name="button1"Width="75"Click="button1_Click">开始</Button>
</Canvas>
在界面上放一个圆和一个按钮
然后在按钮单击事件里写上
//1.创建一个故事板Storyboardstoryboard=newStoryboard();//2.创建关键帧动画
DoubleAnimationUsingKeyFramesdoubleAnimationUsingKeyFrames=newDoubleAnimationUsingKeyFrames();storyboard.Children.Add(doubleAnimationUsingKeyFrames);//把动画添加到故事板Storyboard.SetTarget(doubleAnimationUsingKeyFrames,ellipse1);//设置TargetStoryboard.SetTargetProperty(doubleAnimationUsingKeyFrames,newPropertyPath("(Canvas.Top)"));//设置TargetPropertydoubleAnimationUsingKeyFrames.Duration=newDuration(TimeSpan.FromSeconds(10));//3.创建关键帧并添加到KeyFrames中这里创建了3个样条关键帧LinearDoubleKeyFramelinearDoubleKeyFrame=newLinearDoubleKeyFrame(200,KeyTime.FromTimeSpan(TimeSpan.FromSeconds
(2)));doubleAnimationUsingKeyFrames.KeyFrames.Add(linearDoubleKeyFrame);
doubleAnimationUsingKeyFrames.KeyFrames.Add(newDiscreteDoubleKeyFrame(300,KeyTime.FromTimeSpan(TimeSpan.FromSeconds(5))));doubleAnimationUsingKeyFrames.KeyFrames.Add(newSplineDoubleKeyFrame(600,KeyTime.FromTimeSpan(TimeSpan.FromSeconds(10)),
newKeySpline(newPoint(0,1),newPoint(1,0))));storyboard.Begin();
在这个关键帧动画中,前两秒我们让对象的值从0到200的线性插值,在从2到5秒的时间里对象的值从200到300的离散插值,在5到10秒的时间里对象的值从300到600的样条插值.
这里的对象的值,即ellipse1这个对象的Canvas.Top的值。
关键帧动画的类型属性类型对应的关键帧动画类支持的内插方法ColorColorAnimationUsingKeyFrames离散、线性、样条DoubleDoubleAnimationUsingKeyFrames离散、线性、样条PointPointAnimationUsingKeyFrames离散、线性、样条ObjectObjectAnimationUsingKeyFrames离散和From/To/By动画相比多了一个Object类型的动画
关键帧和关键时间
关键帧的主要用途是指定KeyTime和目标Value。
每一个关键帧都提供了这两个属性。
Value属性指定了关键帧的目标值
KeyTime属性指定了到达关键帧的Value的时间,这个时间在Duration限定的时间内
关键帧开始后,会按照KeyTime属性定义的顺序来循环方位其关键帧。
如果0上没有关键帧,动画将在目标属性当前值和第一帧的Value之间创建一个过渡
动画会使用由第二帧指定的内插方法来创建第一个和第二个关键帧的Value之间的过渡。
过渡从第一帧的KeyTime开始,第二帧的KeyTime结束动画将继续,并创建每个后续关键帧及其前面的关键帧之间的过渡。
最终,动画过渡到关键时间最大(等于或小于动画的Duration)的关键帧值。
关键帧的类型
关键帧的类型主要有Discrete、Linear、Spline三种类型(离散、线性、样条)
关键帧类型遵循以下命名约定:
_interpolationMethod_typeKeyFrame
其中,_interpolationMethod是关键帧使用的内插方法(Discrete、Linear、Spline),_type是类要进行动画处理的值的类型(Double,Color,Point,Object)。
这里object只支持离散的插值方法。
例如,您可以使用以下三种具有DoubleAnimationUsingKeyFrames的关键帧类型:
DiscreteDoubleKeyFrame、LinearDoubleKeyFrame和SplineDoubleKeyFrame。
内插方法
Linear(线性插值):
线性插值应该是最好理解的方法,动画将在持续的时间内以固定的速度来播放。
时间和值的关系是一个线性的关系。
Discrete(离散插值):
使用离散插值,动画函数将从一个值跳到下一个没有内插的值。
它的值是一个跳跃的值。
Spline(样条插值):
使用样条插值可以用于达到更现实的计时效果。
在指定Value和KeyTime的同时,还可以指定KeySpline,用两个控制点,来指定关键帧进度的三次方贝塞尔曲线。
当然样条插值比较难理解。
如下图:
WPF图片水滴马赛克效果
马赛克(Mosaic),建筑专业名词为锦砖,分为陶瓷锦砖和玻璃锦砖两种。
是一种装饰艺术,通常使用许多小石块或有色玻璃碎片拼成图案,在教堂中的玻璃艺品,又称为花窗玻璃(stainedglass)。
在拜占庭帝国时代,马赛克随着基督教兴起而发展为教堂及宫殿中的壁画形式。
现今马赛克泛指这种类型五彩斑斓的视觉效果。
马赛克也指现行广为使用的一种图像(视频)处理手段,此手段将影像特定区域的色阶细节劣化并造成色块打乱的效果,因为这种模糊看上去有一个个的小格子组成,便形象的称这种画面为马赛克。
其目的通常是使之无法辨认。
先来看一下程序的运行结果:
要实现这个效果,我们是通过图片的Clip属性。
图片的Cilp属性
用于确定剪辑区域大小的几何图形。
一个典型的例子如下:
在没有使用Clip属性之前图片是这样的:
使用的代码是MSDN上的代码
<Image
Source="sampleImages\Waterlilies.jpg"
Width="200"Height="150"HorizontalAlignment="Left">
<Image.Clip>
<EllipseGeometry
RadiusX="100"
RadiusY="75"
Center="100,75"/>
</Image.Clip>
</Image>
使用了Clip属性之后:
CompositionTarget.Rendering
CompositionTarget是一个类,表示正在其上绘制您的应用程序的显示图面。
WPF动画引擎为创建基于帧的动画提供了许多功能。
但是,在有些应用程序方案中,您需要根据每个帧控制呈现。
使用CompositionTarget对象,可以基于每个帧回调来创建自定义动画。
我们在程序中使用这个重绘的方法来重绘屏幕,具体的代码如下:
voidCompositionTarget_Rendering(objectsender,EventArgse)
{
doublespringness=Spring;
doublescale=1;//遍历每一个图片
for(inti=0;i<images.Length;i++)
{
//当前的图片
Imageimage=images[i];//根据目标点重定位图片
doubleoffsetX=-(image.Width-ImageWidth)/ImageWidth*targetPoint.X;
doubleoffsetY=-(image.Height-ImageHeight)/ImageHeight*targetPoint.Y;
image.SetValue(Canvas.LeftProperty,offsetX);
image.SetValue(Canvas.TopProperty,offsetY);//更新马赛克
EllipseGeometryellipseGeometry=(EllipseGeometry)image.Clip;
Pointcenter=ellipseGeometry.Center;
center.X=center.X+(targetPoint.X-offsetX-center.X)*springness;
center.Y=center.Y+(targetPoint.Y-offsetY-center.Y)*springness;
ellipseGeometry.Center=center;
image.Clip=ellipseGeometry;springness*=SpringDrag;
scale+=LayerScale;
}
}
打造马赛克
我们使用多重图片堆叠来打造马赛克,具体的代码如下:
///<summary>
///将打过马赛克的图片添加到窗体中
///</summary>
privatevoidaddImage()
{
doubleradius=InitialRadius;//初始半径
doublescale=1;ImageSourceimageSource=newBitmapImage(newUri(ImagePath,UriKind.Relative));
//遍历层数
for(inti=0;i<LayerCount;i++)
{
//创建马赛克
EllipseGeometryellipseGeometry=newEllipseGeometry();
ellipseGeometry.Center=newPoint(0,0);
ellipseGeometry.RadiusX=radius;
ellipseGeometry.RadiusY=radius;doubleoffsetX=ImageWidth*(1-scale)/2;
doubleoffestY=ImageHeight*(1-scale)/2;//创建图片,并设置图片的位置
Imageimage=newImage();
image.Source=imageSource;
image.Width=I
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- wpf 学习 动画