动画是改变控件的一些属性,加一时间元素 。通常结合“呈现变形”,即控件的RenderTransform来完成
一个元素可以完成的作画叫AnimationTimeLine,多个UI元素组合起来的叫Storyboard
简单动画就DoubleAnimationBase派生类用得最多
1.简单线性动画
几个重要属性:
变化时间(Duration)
变化终点(To属性)
变化幅度(By属性)
变化起点(From属性)
<Grid>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="103,72,0,0" VerticalAlignment="Top" Width="75" RenderTransformOrigin="0.5,0.5" Click="button_Click">
<Button.RenderTransform>
<TransformGroup>
<TranslateTransform X="0" Y="0" x:Name="tt"/>
<!--(偏移变形)-->
<!--
MatrixTransform矩陈变形
RotateTransform旋转变形
ScaleTransform坐标变形
SkewTransform拉伸变形
TranslateTransform偏移变形
TransformGroup变形组,多个独立变形合成一个变形组,产生复合效果
-->
</TransformGroup>
</Button.RenderTransform>
</Button>
</Grid>
private void button_Click(object sender, RoutedEventArgs e)
{
DoubleAnimation daX = new DoubleAnimation();
DoubleAnimation daY = new DoubleAnimation();
//若不想每都从0,0坐标开始,则不给From赋值就是从当前开始
daX.From = 0D;
daY.From = 0D;
daX.To = (new Random()).NextDouble() * 300;
daY.To = (new Random()).NextDouble() * 300;
Duration dr = new Duration(TimeSpan.FromMilliseconds(300));
daX.Duration = dr;
daY.Duration = dr;
this.tt.BeginAnimation(TranslateTransform.XProperty, daX);
//如果少了这条,则只是水平移动,没了y轴
this.tt.BeginAnimation(TranslateTransform.YProperty,daY);
}
其实就是给好目标的XY坐标值,然后元素向目标点走直线形成的动画
2.高级动画控制
就是多了几个属性:
AccelerationRatio 加速速率,介于0.00和1.0之间,与DecclerationRation之和不大于1.0,如模拟汽车启动
DecclerationRation减速速率,介于0.00和1.0之间,与AccelerationRatio 之和不大于1.0,如模拟汽车刹车
SpeedRation动画实际播放速度与正常速度的比值 如快进播放、慢动作
AutoReverse 是否以相反的动画方式从终点值返回起始值 如倒退播放
RepeatBehavior动画的重复行为,取0为不播放,使用double类型值可控制循环次数,取RepeatBehavior.Forever永不停
BeginTime正式开始播放前的等待时间 常用于多个动画协同
EasingFunction缓冲式渐变 如乒乓球弹跳效果
以下示例向乒乓球掉在地止弹起3次再停止
private void button_Click(object sender, RoutedEventArgs e)
{
DoubleAnimation daX = new DoubleAnimation();
DoubleAnimation daY = new DoubleAnimation();
daX.From = 0D;
daY.From = 0D;
BounceEase be = new BounceEase();
be.Bounces = 52;//跳跃3次
be.Bounciness = 2;//弹性程序,值越大反弹越低
daY.EasingFunction = be;
daX.To = 2 * 300;
daY.To = 2 * 300;
Duration dr = new Duration(TimeSpan.FromMilliseconds(10000));
daX.Duration = dr;
daY.Duration = dr;
this.tt.BeginAnimation(TranslateTransform.XProperty, daX);
//如果少了这条,则只是水平移动,没了y轴
this.tt.BeginAnimation(TranslateTransform.YProperty,daY);
}
3.关键帧动画
就是定几个位置,然后指定什么时间到这个点,什么时候到那个点就,程序就会自动在时间内均匀地到达,这样就不需要把几个动作协同了,很是方便
以下为按钮走z字形动画
private void button_Click(object sender, RoutedEventArgs e)
{
DoubleAnimationUsingKeyFrames daX = new DoubleAnimationUsingKeyFrames();
DoubleAnimationUsingKeyFrames daY = new DoubleAnimationUsingKeyFrames();
//总时间长
Duration dr = new Duration(TimeSpan.FromMilliseconds(10000));
daX.Duration = dr;
daY.Duration = dr;
//创建并添加X关键帧
LinearDoubleKeyFrame x_kf_1 = new LinearDoubleKeyFrame(200,KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(3000)));
LinearDoubleKeyFrame x_kf_2 = new LinearDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(5000)));
LinearDoubleKeyFrame x_kf_3 = new LinearDoubleKeyFrame(200, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(10000)));
daX.KeyFrames.Add(x_kf_1);
daX.KeyFrames.Add(x_kf_2);
daX.KeyFrames.Add(x_kf_3);
//创建并添加Y关键帧
LinearDoubleKeyFrame Y_kf_1 = new LinearDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(3000)));
LinearDoubleKeyFrame Y_kf_2 = new LinearDoubleKeyFrame(180, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(5000)));
LinearDoubleKeyFrame Y_kf_3 = new LinearDoubleKeyFrame(180, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(10000)));
daY.KeyFrames.Add(Y_kf_1);
daY.KeyFrames.Add(Y_kf_2);
daY.KeyFrames.Add(Y_kf_3);
this.tt.BeginAnimation(TranslateTransform.XProperty, daX);
//如果少了这条,则只是水平移动,没了y轴
this.tt.BeginAnimation(TranslateTransform.YProperty,daY);
}
4.特殊关键帧动画
KeyFrames接收类型除了LinearDoubleKeyFrame(线性变化关键帧),还有:
DiscreteDoubleKeyFrame:不连续变化关键帧
SplineDoubleKeyFrame:样条函数式变化关键帧,目标属性值的变化速率是一条贝赛尔贝线,常用
EasingDoubleKeyFrame:缓冲式变化关键帧
private void button_Click(object sender, RoutedEventArgs e)
{
DoubleAnimationUsingKeyFrames daX = new DoubleAnimationUsingKeyFrames();
DoubleAnimationUsingKeyFrames daY = new DoubleAnimationUsingKeyFrames();
//总时间长
Duration dr = new Duration(TimeSpan.FromMilliseconds(10000));
daX.Duration = dr;
daY.Duration = dr;
//创建并添加X关键帧
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;
daX.KeyFrames.Add(kf);
this.tt.BeginAnimation(TranslateTransform.XProperty, daX);
//如果少了这条,则只是水平移动,没了y轴
// this.tt.BeginAnimation(TranslateTransform.YProperty,daY);
}
最终结果是开始快,中间慢,后半部分又快
4.路径动画
绘制一条路径,然后让目标沿着一条给定的路径移动 ,使用DoubleAnimationUsingPath类。需要一个PathGeometry来指明移动的路径
<Window.Resources>
<PathGeometry x:Key="movePath" Figures="M 0,150 C300,-100 300,400 600,120"></PathGeometry>
</Window.Resources>
private void button_Click(object sender, RoutedEventArgs e)
{
var pg = this.FindResource("movePath") as PathGeometry;
var du = new Duration(TimeSpan.FromMilliseconds(1000));
DoubleAnimationUsingPath daX = new DoubleAnimationUsingPath();
daX.PathGeometry = pg;
daX.Source = PathAnimationSource.X;(获取坐标值的X值)
daX.Duration = du;
var daY = new DoubleAnimationUsingPath();
daY.PathGeometry = pg;
daY.Source = PathAnimationSource.Y;(获取坐标值的X值)
daY.Duration = du;
this.tt.BeginAnimation(TranslateTransform.XProperty, daX);
this.tt.BeginAnimation(TranslateTransform.YProperty,daY);
}
//加上下面代码可永远运动
daX.AutoReverse = true;
daX.RepeatBehavior = RepeatBehavior.Forever;
daY.AutoReverse = true;
daY.RepeatBehavior = RepeatBehavior.Forever;
场景动画
场景动画就是多个元素组成一起的动画,一般是在xaml里写法,后台代码写很是复杂
<Grid>
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="22" Margin="18,39,0,0" VerticalAlignment="Top" Width="254 ">
<Ellipse Fill="Red" Stroke="Black" Width="20" HorizontalAlignment="Left" RenderTransformOrigin="0.5,0.5" >
<Ellipse.RenderTransform>
<TranslateTransform x:Name="ttr"/>
</Ellipse.RenderTransform>
</Ellipse>
</Border>
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="22" Margin="18,61,0,0" VerticalAlignment="Top" Width="254">
<Ellipse Fill="Green" Stroke="Black" Width="20" HorizontalAlignment="Left" >
<Ellipse.RenderTransform>
<TranslateTransform x:Name="ttg"/>
</Ellipse.RenderTransform>
</Ellipse>
</Border>
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="22" Margin="18,83,0,0" VerticalAlignment="Top" Width="254">
<Ellipse Fill="Blue" Stroke="Black" Width="20" HorizontalAlignment="Left" >
<Ellipse.RenderTransform>
<TranslateTransform x:Name="ttb"/>
</Ellipse.RenderTransform>
</Ellipse>
</Border>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="18,123,0,0" VerticalAlignment="Top" Width="75" >
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard Duration="0:0:1">
<!--红色移动(匀速)-->
<DoubleAnimation Duration="0:0:1" To="400" Storyboard.TargetName="ttr" Storyboard.TargetProperty="X"></DoubleAnimation>
<!--绿色移动(以加速的方式) -->
<DoubleAnimationUsingKeyFrames Duration="0:0:1" Storyboard.TargetName="ttg" Storyboard.TargetProperty="X">
<SplineDoubleKeyFrame KeyTime="0:0:1" Value="400" KeySpline="1,0,0,1"></SplineDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<!--蓝色移动(以加速的方式) -->
<DoubleAnimationUsingKeyFrames Duration="0:0:1" Storyboard.TargetName="ttb" Storyboard.TargetProperty="X">
<SplineDoubleKeyFrame KeyTime="0:0:1" Value="400" KeySpline="1,0,0,1"></SplineDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>