如今的软件市场,竞争已经进入白热化阶段,功能强、运算快、界面友好、Bug少、价格低都已经成为了必备条件。这还不算完,随着计算机的多媒体功能越来越强,软件的界面是否色彩亮丽、是否能通过动画、3D等效果是否吸引用户的眼球也已经成为衡量软件的标准。
软件项目成功的三个要素是:资源、成本、时间。无论是为了在竞争中保持不败还是为了激发起用户对软件的兴趣,提高软件界面的美化程度、恰当的将动画和3D等效果引入应用程序都是一个必然趋势。然而使用传统的桌面应用程序开发工具和框架(如Winform、MFC、VB、Delphi等)进行开发时,为了使软件界面变漂亮、加入动画或者3D效果,边际成本会非常的高。体现在:
资源消耗增大:需要招聘懂得动画和3D编程的程序员,还需要更多的设计师、工薪和沟通成本随着上升。
开发时间增加:界面美化、动画和3D开发远远比业务逻辑开发困难、耗时。
成本增加:随着资源消耗的增加和开发周期的拉长,成本必然增加。
之所以会出现这种情况,根本原因在于传统开发工具和框架并没有原生的支持美化用户界面、向应用程序中添加动画和3D效果等功能。举个简单的例子,当用户提出需要把TextBox的外观改成圆角时,Winform和Delphi程序员只能通过派生新类并在底层做修改的方法来实现。类似的用户需求还有好多不得不实现,否则客户会怀疑我们的开发能力;即使实现了也没有什么额外的经济效益,因为这些东西在客户的眼里都是很简单的东西。
WPF的推出可谓是对症下药、专门解决上述问题。体现在:
XAML语言针对的是界面美化的问题,可以让设计师直接加入开发团队、降低沟通成本。
XAML的图形绘制功能非常强大,可以轻易绘出复杂的图标、图画。
WPF支持滤镜功能,可以像PhotoShop一样为对象添加各种效果。
WPF原生支持动画开发,无论是设计师还是程序员,都能够使用XAML或C#轻松开发制作绚丽的动画效果。
WPF原生支持3D效果,甚至可以将其它3D建模工具创建的模型导进来、为我所用。
Blend作为专门的设计工具让WPF如虎添翼,即能够帮助不了解编程的设计师快速上手,又能够帮助资深开发者快速建立图形或者动画的原型。
1.1 WPF绘图
与传统的.net开发使用GDI+进行绘图不同,WPF拥有自己的一套绘图API。使用这套API不但可以轻松绘制出精美的图形,还可以为各种图形添加类似与PhotoShop的“滤镜效果”及“变形效果”。本节我们就一起研究WPF图形API绘图,效果和变形等功能。
先观察下面一组图片:
显然,这组图片是矢量图(Vector Image),无论怎样放大缩小都不会出现锯齿。你可能会想:“这是组PNG格式的图片吗?”答案是“NO”。这组图是用XAML语言绘制的!XAML绘图本身就是矢量的,而且支持各式各样的填充和效果,甚至还可以添加滤镜,这些功能丝毫不亚于Photoshop。以前,使用PhotoShop制作出来的图形需要程序员使用.net的绘图接口进行二次转换才能应用到程序里,现在好了,直接把XAML代码拿来用就可以了。
绘图并不是VisualStudio的强项,这些漂亮的XAML矢量图是怎么画出来的呢?答案是借助Microsoft Expression Studio中的Blend和Design两个工具。Blend我们已经介绍过了,用它可以直接绘制XAML图形;Design可以像PhotoShop或者FireWorks那样绘制图形,再由设计者决定导出xaml格式还是png格式。虽然“唯代码派”的程序员们在Visualstudio里一行一行写代码也能把复杂的图形以非可视化的形式创建出来,但在Blend和Design中画出原型再在Visual Studio里面进行细节的修饰才是提高效率之道。
积沙成塔,集腋成裘,别看前面那些图片很复杂,但都是由几个有限的基本图形组成的。WPF的基本图形包括以下几个(它们都是Shap类的派生类):
Line:直线段,可以设置其笔触(Stroke)。
Rectangle:矩形,既有笔触,又有填充(Fill)。
Ellipse:椭圆,长宽相等的椭圆即为正圆,既有笔触又有填充。
Polygon:多边形,由多条直线线段围成的闭合区域,既有笔触又有填充。
PolyLine:折线(不闭合),由多条首尾相接的直线组成。
Path:路径(闭合区域),基本图形中功能最强的一个,可由若干直线,圆弧,被塞尔曲线组成。
1 直线
直线是最简单的图形。使用X1,Y1两个属性值可以设置它的起点坐标,X2,Y2两个属性值可以设置它的终点坐标。控制终点/起点做标就可以实现平行,交错等效果。Stroke(笔触)属性的数据类型是Brush(画刷),凡是Brush的派生类均可以用于给这个属性赋值。因为WPF提供多种渐变色画刷,所以画直线也可以画出渐变效果。同时,Line的一些属性还可以帮助我们画出虚线以及控制线段终点的形状。下面的例子综合了这些属性:
[html] view plain copy - <Window x:Class="WpfApplication1.Window47"
- "http://schemas.microsoft.com/get='_blank'>winfx/2006/xaml/presentation"
- "http://schemas.microsoft.com/winfx/2006/xaml"
- Title="Window47" Height="300" Width="400" Background="Orange">
- <Grid Margin="10">
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="160" />
- <ColumnDefinition Width="*" />
- <ColumnDefinition Width="160" />
- </Grid.ColumnDefinitions>
- <StackPanel Background="White" x:Name="spleft">
- <Button Height="40" Content="OK" x:Name="btnReal" Click="btnReal_Click"></Button>
- </StackPanel>
- <Button Grid.Column="1" Content=">>" Margin="5,0"></Button>
- <StackPanel Grid.Column="2" Background="White" x:Name="spRight">
-
- </StackPanel>
- </Grid>
- </Window>
- double o = 1;//不透明度指数
- private void btnReal_Click(object sender, RoutedEventArgs e)
- {
- VisualBrush vb = new VisualBrush(this.btnReal);
- Rectangle rtg = new Rectangle();
- rtg.Width = btnReal.Width;
- rtg.Height = btnReal.Height;
- rtg.Fill = vb;
- rtg.Opacity = o;
- o -= 0.2;
- this.spRight.Children.Add(rtg);
- }
- <Window x:Class="WpfApplication1.Window48"
- "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- "http://schemas.microsoft.com/winfx/2006/xaml"
- Title="Window48" Height="300" Width="300">
- <Grid>
- <Ellipse Height="140" Name="ellipse1" Stroke="Gray" Width="140" Cursor="Hand" ToolTip="A Ball">
- <Ellipse.Fill>
- <RadialGradientBrush GradientOrigin="0.2,0.8" RadiusX="0.75" RadiusY="0.75">
- <RadialGradientBrush.RelativeTransform>
- <TransformGroup>
- <RotateTransform Angle="90" CenterX="0.5" CenterY="0.5"></RotateTransform>
- </TransformGroup>
- </RadialGradientBrush.RelativeTransform>
- <GradientStop Color="#FFFFFFFF" Offset="0" />
- <GradientStop Color="#FF444444" Offset="0.66" />
- <GradientStop Color="#FF999999" Offset="1" />
- </RadialGradientBrush>
- </Ellipse.Fill>
- </Ellipse>
- </Grid>
- </Window>
- <Window x:Class="WpfApplication1.Window49"
- "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- "http://schemas.microsoft.com/winfx/2006/xaml"
- Title="Window49" Height="350" Width="340">
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition Height="160" />
- <RowDefinition Height="160" />
- </Grid.RowDefinitions>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="160" />
- <ColumnDefinition Width="160" />
- </Grid.ColumnDefinitions>
- <!--直线-->
- <Path Stroke="Blue" StrokeThickness="2" Grid.Row="0" Grid.Column="0">
- <Path.Data>
- <LineGeometry StartPoint="0,0" EndPoint="160,160"></LineGeometry>
- </Path.Data>
- </Path>
- <!--矩形路径-->
- <Path Stroke="Orange" Fill="Yellow" Grid.Row="0" Grid.Column="1">
- <Path.Data>
- <RectangleGeometry Rect="20,20,120,120" RadiusX="10" RadiusY="10"></RectangleGeometry>
- </Path.Data>
- </Path>
- <!--椭圆路径-->
- <Path Stroke="Green" Fill="LawnGreen" Grid.Column="0" Grid.Row="1">
- <Path.Data>
- <EllipseGeometry Center="80,80" RadiusX="60" RadiusY="40"></EllipseGeometry>
- </Path.Data>
- </Path>
- <!--自定义路径-->
- <Path Stroke="Yellow" Fill="Orange" Grid.Row="1" Grid.Column="1">
- <Path.Data>
- <PathGeometry>
- <PathGeometry.Figures>
- <PathFigure StartPoint="25,140" IsClosed="True">
- <PathFigure.Segments>
- <LineSegment Point="20,40"></LineSegment>
- <LineSegment Point="40,110"></LineSegment>
- <LineSegment Point="50,20"></LineSegment>
- <LineSegment Point="80,110"></LineSegment>
- <LineSegment Point="110,20"></LineSegment>
- <LineSegment Point="120,110"></LineSegment>
- <LineSegment Point="140,40"></LineSegment>
- <LineSegment Point="135,140"></LineSegment>
- </PathFigure.Segments>
- </PathFigure>
- </PathGeometry.Figures>
- </PathGeometry>
- </Path.Data>
- </Path>
- </Grid>
- </Window>
- <Path>
- <Path.Data>
- <PathGeometry>
- <PathGeometry.Figures>
- <PathFigure>
- <PathFigure.Segments>
- <!--线段内容-->
- </PathFigure.Segments>
- </PathFigure>
- </PathGeometry.Figures>
- </PathGeometry>
- </Path.Data>
- </Path>
- <Window x:Class="WpfApplication1.Window53"
- "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- "http://schemas.microsoft.com/winfx/2006/xaml"
- Title="Window53" Height="300" Width="300">
- <Grid>
- <Path Stroke="Black" Fill="LightBlue" StrokeThickness="1">
- <Path.Data>
- <GeometryGroup>
- <PathGeometry>
- <PathFigure StartPoint="0,0">
- <BezierSegment Point1="250,0" Point2="50,200" Point3="300,200"></BezierSegment>
- </PathFigure>
- </PathGeometry>
- <PathGeometry>
- <PathFigure StartPoint="0,0">
- <BezierSegment Point1="230,0" Point2="50,200" Point3="300,200"></BezierSegment>
- </PathFigure>
- </PathGeometry>
- <PathGeometry>
- <PathFigure StartPoint="0,0">
- <BezierSegment Point1="210,0" Point2="50,200" Point3="300,200"></BezierSegment>
- </PathFigure>
- </PathGeometry>
- <PathGeometry>
- <PathFigure StartPoint="0,0">
- <BezierSegment Point1="190,0" Point2="50,200" Point3="300,200"></BezierSegment>
- </PathFigure>
- </PathGeometry>
- <PathGeometry>
- <PathFigure StartPoint="0,0">
- <BezierSegment Point1="170,0" Point2="50,200" Point3="300,200"></BezierSegment>
- </PathFigure>
- </PathGeometry>
- <PathGeometry>
- <PathFigure StartPoint="0,0">
- <BezierSegment Point1="150,0" Point2="50,200" Point3="300,200"></BezierSegment>
- </PathFigure>
- </PathGeometry>
- <PathGeometry>
- <PathFigure StartPoint="0,0">
- <BezierSegment Point1="130,0" Point2="50,200" Point3="300,200"></BezierSegment>
- </PathFigure>
- </PathGeometry>
- </GeometryGroup>
- </Path.Data>
- </Path>
- </Grid>
- </Window>
- <Window x:Class="WpfApplication1.Window56"
- "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- "http://schemas.microsoft.com/winfx/2006/xaml"
- Title="Window56" Height="250" Width="300" WindowStyle="None" AllowsTransparency="True" WindowStartupLocation="CenterScreen" Background="Yellow">
- <Grid VerticalAlignment="Center" HorizontalAlignment="Center">
- <Path Stroke="Orange" Fill="Yellow" x:Name="clipPath0" Visibility="Hidden" Data="M 55,100 A 50,50 0 1 1 100,60 A 110,95 0 0 1 200,60 A 50,50 0 1 1 250,100 A 110,95 0 1 1 55,100 Z">
- </Path>
- <Button Content="Clip" Width="80" Height="25" Click="Button_Click" HorizontalAlignment="Center" VerticalAlignment="Center"></Button>
- </Grid>
- </Window>
- private void Button_Click(object sender, RoutedEventArgs e)
- {
- this.Clip = clipPath0.Data;
- }
- <Window x:Class="WpfApplication1.Window57"
- "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- "http://schemas.microsoft.com/winfx/2006/xaml"
- Title="Window57" Height="300" Width="300">
- <Grid>
- <Button Width="80" Height="50">
- <Button.BitmapEffect>
- <DropShadowBitmapEffect Direction="-45" Opacity="0.75" Color="Red" ShadowDepth="7"></DropShadowBitmapEffect>
- </Button.BitmapEffect>
- </Button>
- </Grid>
- </Window>
- <Window x:Class="WpfApplication1.Window60"
- "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- "http://schemas.microsoft.com/winfx/2006/xaml"
- Title="Window60" Height="338" Width="471">
- <Grid x:Name="titleBar" Background="LightBlue">
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="Auto"></ColumnDefinition>
- <ColumnDefinition Width="*"></ColumnDefinition>
- </Grid.ColumnDefinitions>
- <TextBlock FontSize="24" Text="Hello Transformer" VerticalAlignment="Bottom" HorizontalAlignment="Center">
- <TextBlock.RenderTransform>
- <RotateTransform Angle="-90"></RotateTransform>
- </TextBlock.RenderTransform>
- </TextBlock>
- </Grid>
- </Window>
- <Window x:Class="WpfApplication1.Window61"
- "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- "http://schemas.microsoft.com/winfx/2006/xaml"
- Title="Window61" Height="372" Width="475">
- <Grid>
- <Button Width="80" Height="80" HorizontalAlignment="Left" VerticalAlignment="Top">
- <Button.RenderTransform>
- <TranslateTransform X="0" Y="0" x:Name="tt"></TranslateTransform>
- </Button.RenderTransform>
- </Button>
- </Grid>
- </Window>
- private void Button_Click(object sender, RoutedEventArgs e)
- {
- DoubleAnimation dax = new DoubleAnimation();
- DoubleAnimation day = new DoubleAnimation();
- //指定起点
- dax.From = 0;
- day.From = 0;
- //指定终点
- Random rdm = new Random();
- dax.To = rdm.NextDouble() * 300;
- day.To = rdm.NextDouble() * 300;
- //指定时长
- Duration duration = new Duration(TimeSpan.FromMilliseconds(3000));
- dax.Duration = duration;
- day.Duration = duration;
- //动画主体是TranslatTransform变形,而非Button
- this.tt.BeginAnimation(TranslateTransform.XProperty,dax);
- this.tt.BeginAnimation(TranslateTransform.YProperty,day);
- }
- private void Button_Click(object sender, RoutedEventArgs e)
- {
- DoubleAnimation dax = new DoubleAnimation();
- DoubleAnimation day = new DoubleAnimation();
-
- //设置反弹
- BounceEase be = new BounceEase();
- //设置反弹次数为3
- be.Bounces = 3;
- be.Bounciness = 3;//弹性程度,值越大反弹越低
- day.EasingFunction = be;
-
- //设置终点
- dax.To = 300;
- day.To = 300;
-
- //指定时长
- Duration duration = new Duration(TimeSpan.FromMilliseconds(2000));
- dax.Duration = duration;
- day.Duration = duration;
- //动画主体是TranslatTransform变形,而非Button
- this.tt.BeginAnimation(TranslateTransform.XProperty,dax);
- this.tt.BeginAnimation(TranslateTransform.YProperty,day);
- }
- <Window x:Class="WpfApplication1.Window61"
- "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- "http://schemas.microsoft.com/winfx/2006/xaml"
- Title="Window61" Height="372" Width="475">
- <Grid>
- <Button Width="80" Height="80" HorizontalAlignment="Left" VerticalAlignment="Top" Click="Button_Click">
- <Button.RenderTransform>
- <TranslateTransform X="0" Y="0" x:Name="tt"></TranslateTransform>
- </Button.RenderTransform>
- </Button>
- </Grid>
- </Window>
- private void Button_Click(object sender, RoutedEventArgs e)
- {
- DoubleAnimationUsingKeyFrames dakX = new DoubleAnimationUsingKeyFrames();
- DoubleAnimationUsingKeyFrames dakY = new DoubleAnimationUsingKeyFrames();
- //设置动画总时长
- dakX.Duration = new Duration(TimeSpan.FromMilliseconds(900));
- dakY.Duration = new Duration(TimeSpan.FromMilliseconds(900));
- //创建,添加关键帧
- LinearDoubleKeyFrame x_kf_1 = new LinearDoubleKeyFrame();
- LinearDoubleKeyFrame x_kf_2 = new LinearDoubleKeyFrame();
- LinearDoubleKeyFrame x_kf_3 = new LinearDoubleKeyFrame();
- x_kf_1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300));
- x_kf_1.Value = 200;
- x_kf_2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(600));
- x_kf_2.Value = 0;
- x_kf_3.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(900));
- x_kf_3.Value = 200;
- dakX.KeyFrames.Add(x_kf_1);
- dakX.KeyFrames.Add(x_kf_2);
- dakX.KeyFrames.Add(x_kf_3);
-
- LinearDoubleKeyFrame y_kf_1 = new LinearDoubleKeyFrame();
- LinearDoubleKeyFrame y_kf_2 = new LinearDoubleKeyFrame();
- LinearDoubleKeyFrame y_kf_3 = new LinearDoubleKeyFrame();
- y_kf_1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300));
- y_kf_1.Value = 0;
- y_kf_2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(600));
- y_kf_2.Value = 180;
- y_kf_3.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(900));
- y_kf_3.Value = 180;
- dakY.KeyFrames.Add(y_kf_1);
- dakY.KeyFrames.Add(y_kf_2);
- dakY.KeyFrames.Add(y_kf_3);
-
- //执行动画
- tt.BeginAnimation(TranslateTransform.XProperty, dakX);
- tt.BeginAnimation(TranslateTransform.YProperty,dakY);
- }
- x_kf_1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300));
- x_kf_1.Value = 200;
- x_kf_2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(600));
- x_kf_2.Value = 0;
- private void Button_Click(object sender, RoutedEventArgs e)
- {
- //创建动画
- DoubleAnimationUsingKeyFrames dakX = new DoubleAnimationUsingKeyFrames();
- dakX.Duration = new Duration(TimeSpan.FromMilliseconds(1000));
-
- //创建、添加关键帧
- SplineDoubleKeyFrame kf = new SplineDoubleKeyFrame();
- kf.KeyTime = KeyTime.FromPercent(1);
- kf.Value = 400;
-
- KeySpline ks = new KeySpline();
- ks.ControlPoint1 = new Point(0,1);
- ks.ControlPoint2 = new Point(1,0);
-
- kf.KeySpline = ks;
- dakX.KeyFrames.Add(kf);
-
- //执行动画
- this.tt.BeginAnimation(TranslateTransform.XProperty ,dakX);
- }
- <Window x:Class="WpfApplication1.Window63"
- "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- "http://schemas.microsoft.com/winfx/2006/xaml"
- Title="Window63" Height="314" Width="517">
- <Grid x:Name="layoutRoot">
- <Grid.Resources>
- <!--移动路径-->
- <PathGeometry x:Key="movePath" Figures="M 0,50 C 300,-100 300,400 600,120"></PathGeometry>
- </Grid.Resources>
- <Button Content="Move" Width="80" Height="80" HorizontalAlignment="Left" VerticalAlignment="Top" Click="Button_Click">
- <Button.RenderTransform>
- <TranslateTransform X="0" Y="0" x:Name="tt"></TranslateTransform>
- </Button.RenderTransform>
- </Button>
- </Grid>
- </Window>
- private void Button_Click(object sender, RoutedEventArgs e)
- {
- //从XAML代码中获取移动路径数据
- PathGeometry pg = this.layoutRoot.FindResource("movePath") as PathGeometry;
- Duration duration = new Duration(TimeSpan.FromMilliseconds(600));
-
- //创建动画
- DoubleAnimationUsingPath dpX = new DoubleAnimationUsingPath();
- dpX.Duration = duration;
- dpX.PathGeometry = pg;
- dpX.Source = PathAnimationSource.X;
-
- DoubleAnimationUsingPath dpY = new DoubleAnimationUsingPath();
- dpY.Duration = duration;
- dpY.PathGeometry = pg;
- dpY.Source = PathAnimationSource.Y;
-
- //执行动画
- this.tt.BeginAnimation(TranslateTransform.XProperty,dpX);
- this.tt.BeginAnimation(TranslateTransform.YProperty,dpY);
-
- }
- dpX.AutoReverse = true;
- dpX.RepeatBehavior = RepeatBehavior.Forever;
- dpY.AutoReverse = true;
- dpY.RepeatBehavior = RepeatBehavior.Forever;
- <Window x:Class="WpfApplication1.Window64"
- "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- "http://schemas.microsoft.com/winfx/2006/xaml"
- Title="Window64" Height="159" Width="461">
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition Height="38" />
- <RowDefinition Height="38" />
- <RowDefinition Height="38" />
- </Grid.RowDefinitions>
- <Grid.ColumnDefinitions>
- <ColumnDefinition />
- <ColumnDefinition Width="60" />
- </Grid.ColumnDefinitions>
- <!--跑道(红)-->
- <Border Grid.Row="0" BorderBrush="Gray" BorderThickness="1">
- <Ellipse Width="36" Height="36" Fill="Red" HorizontalAlignment="Left" x:Name="ballR">
- <Ellipse.RenderTransform>
- <TranslateTransform X="0" Y="0" x:Name="ttR">
- </TranslateTransform>
- </Ellipse.RenderTransform>
- </Ellipse>
- </Border>
- <!--跑道(绿)-->
- <Border Grid.Row="1" BorderBrush="Gray" BorderThickness="1,0,1,1">
- <Ellipse Width="36" Height="36" Fill="Green" HorizontalAlignment="Left" x:Name="ballG">
- <Ellipse.RenderTransform>
- <TranslateTransform X="0" Y="0" x:Name="ttG">
- </TranslateTransform>
- </Ellipse.RenderTransform>
- </Ellipse>
- </Border>
- <!--跑道(蓝)-->
- <Border Grid.Row="2" BorderBrush="Gray" BorderThickness="1,0,1,1">
- <Ellipse Width="36" Height="36" Fill="Blue" HorizontalAlignment="Left" x:Name="ballB">
- <Ellipse.RenderTransform>
- <TranslateTransform X="0" Y="0" x:Name="ttB">
- </TranslateTransform>
- </Ellipse.RenderTransform>
- </Ellipse>
- </Border>
- <!--按钮-->
- <Button Content="Go" Grid.RowSpan="3" Grid.Column="1" Click="Button_Click"></Button>
- </Grid>
- </Window>
- private void Button_Click(object sender, RoutedEventArgs e)
- {
- Duration duration = new Duration(TimeSpan.FromMilliseconds(600));
-
- //红色小球匀速运动
- DoubleAnimation daRx = new DoubleAnimation();
- daRx.Duration = duration;
- daRx.To = 400;
-
- //绿色小球做变速运动
- DoubleAnimationUsingKeyFrames dakGx = new DoubleAnimationUsingKeyFrames();
- dakGx.Duration = duration;
- SplineDoubleKeyFrame kfg = new SplineDoubleKeyFrame(400,KeyTime.FromPercent(1));
- kfg.KeySpline = new KeySpline(1,0,0,1);
- dakGx.KeyFrames.Add(kfg);
-
- //蓝色小球变速运动
- DoubleAnimationUsingKeyFrames dakBx = new DoubleAnimationUsingKeyFrames();
- dakBx.Duration = duration;
- SplineDoubleKeyFrame kfb = new SplineDoubleKeyFrame(400,KeyTime.FromPercent(1));
- kfb.KeySpline = new KeySpline(0,1,1,0);
- dakBx.KeyFrames.Add(kfb);
-
- //创建场景
- Storyboard storyBoard = new Storyboard();
- Storyboard.SetTargetName(daRx,"ttR");
- Storyboard.SetTargetProperty(daRx, new PropertyPath(TranslateTransform.XProperty));
-
- Storyboard.SetTargetName(dakGx, "ttG");
- Storyboard.SetTargetProperty(dakGx, new PropertyPath(TranslateTransform.XProperty));
-
- Storyboard.SetTargetName(dakBx, "ttB");
- Storyboard.SetTargetProperty(dakBx, new PropertyPath(TranslateTransform.XProperty));
-
- storyBoard.Duration = duration;
- storyBoard.Children.Add(daRx);
- storyBoard.Children.Add(dakBx);
- storyBoard.Children.Add(dakGx);
-
- storyBoard.Begin(this);
- storyBoard.Completed += (a, b) => { MessageBox.Show(ttR.X.ToString()); };
- }
- <!--按钮-->
- <Button Content="Go" Grid.RowSpan="3" Grid.Column="1" Click="Button_Click">
- <Button.Triggers>
- <EventTrigger RoutedEvent="Button.Click">
- <BeginStoryboard>
- <Storyboard Duration="0:0:0.6">
- <!--红色小球动画-->
- <DoubleAnimation Duration="0:0:0.6" To="400" Storyboard.TargetName="ttR" Storyboard.TargetProperty="X">
-
- </DoubleAnimation>
- <!--绿色小球动画-->
- <DoubleAnimationUsingKeyFrames Duration="0:0:0.6" Storyboard.TargetProperty="X" Storyboard.TargetName="ttG">
- <SplineDoubleKeyFrame KeyTime="0:0:0.6" Value="400" KeySpline="1,0,0,1"></SplineDoubleKeyFrame>
- </DoubleAnimationUsingKeyFrames>
- <!--蓝色小球动画-->
- <DoubleAnimationUsingKeyFrames Duration="0:0:0.6" Storyboard.TargetName="ttB" Storyboard.TargetProperty="X">
- <SplineDoubleKeyFrame KeyTime="0:0:0.6" Value="400" KeySpline="0,1,1,0"></SplineDoubleKeyFrame>
- </DoubleAnimationUsingKeyFrames>
- </Storyboard>
- </BeginStoryboard>
- </EventTrigger>
- </Button.Triggers>
- </Button>