第一种是继承AnimationTimeline 抽象类
指定输出的时间段
public class GridLengthAnimation : AnimationTimeline
{
static GridLengthAnimation()
{
FromProperty = DependencyProperty.Register("From", typeof(GridLength), typeof(GridLengthAnimation));
ToProperty = DependencyProperty.Register("To", typeof(GridLength), typeof(GridLengthAnimation));
}
public override Type TargetPropertyType
{
get
{
return typeof(GridLength);
}
}
protected override System.Windows.Freezable CreateInstanceCore()
{
return new GridLengthAnimation();
}
public static readonly DependencyProperty FromProperty;
public GridLength From
{
get
{
return (GridLength)GetValue(GridLengthAnimation.FromProperty);
}
set
{
SetValue(GridLengthAnimation.FromProperty, value);
}
}
public static readonly DependencyProperty ToProperty;
public GridLength To
{
get
{
return (GridLength)GetValue(GridLengthAnimation.ToProperty);
}
set
{
SetValue(GridLengthAnimation.ToProperty, value);
}
}
public override object GetCurrentValue(object defaultOriginValue, object defaultDestinationValue, AnimationClock animationClock)
{
double fromVal = ((GridLength)GetValue(GridLengthAnimation.FromProperty)).Value;
double toVal = ((GridLength)GetValue(GridLengthAnimation.ToProperty)).Value;
if (fromVal > toVal)
{
return new GridLength((1 - animationClock.CurrentProgress.Value) * (fromVal - toVal) + toVal, GridUnitType.Star);
}
else
return new GridLength(animationClock.CurrentProgress.Value * (toVal - fromVal) + fromVal, GridUnitType.Star);
}
}
<Window x:Class="WpfTest.Window6"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window6" Height="300" Width="300">
<Grid Background="Black" x:Name="mainGrid">
<Grid.Resources>
<Style TargetType="{x:Type Image}">
<Setter Property="Stretch" Value="Fill" />
<Setter Property="Margin" Value="2" />
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" Name="col0" />
<ColumnDefinition Width="*" Name="col1" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" Name="row0" />
<RowDefinition Height="*" Name="row1" />
</Grid.RowDefinitions>
<Image MouseDown="image_MouseDown" Grid.Column="0" Grid.Row="0" Source="/Images/1.ico" />
<Image MouseDown="image_MouseDown" Grid.Column="0" Grid.Row="1" Source="/Images/2.ico" />
<Image MouseDown="image_MouseDown" Grid.Column="1" Grid.Row="0" Source="/Images/3.ico" />
<Image MouseDown="image_MouseDown" Grid.Column="1" Grid.Row="1" Source="/Images/4.ico"/>
</Grid>
</Window>
/// <summary>
/// Window6.xaml 的交互逻辑
/// </summary>
public partial class Window6 : Window
{
public Window6()
{
InitializeComponent();
}
bool bSingleImageMode = false;
void image_MouseDown(object sender, MouseButtonEventArgs e)
{
Image image = sender as Image;
if (image != null)
{
int col = Grid.GetColumn(image);
int row = Grid.GetRow(image);
for (int indexRow = 0; indexRow < mainGrid.RowDefinitions.Count; indexRow++)
{
if (indexRow != row)
{
GridLengthAnimation gla = new GridLengthAnimation();
gla.From = new GridLength(bSingleImageMode ? 0 : 1, GridUnitType.Star);
gla.To = new GridLength(bSingleImageMode ? 1 : 0, GridUnitType.Star); ;
gla.Duration = new TimeSpan(0, 0, 2);
mainGrid.RowDefinitions[indexRow].BeginAnimation(RowDefinition.HeightProperty, gla);
}
}
for (int indexCol = 0; indexCol < mainGrid.ColumnDefinitions.Count; indexCol++)
{
if (indexCol != col)
{
GridLengthAnimation gla = new GridLengthAnimation();
gla.From = new GridLength(bSingleImageMode ? 0 : 1, GridUnitType.Star);
gla.To = new GridLength(bSingleImageMode ? 1 : 0, GridUnitType.Star);
gla.Duration = new TimeSpan(0, 0, 2);
mainGrid.ColumnDefinitions[indexCol].BeginAnimation(ColumnDefinition.WidthProperty, gla);
}
}
}
bSingleImageMode = !bSingleImageMode;
}
}
实现动态的变换布局
第二种是继承抽象类DoubleAnimationBase
public class EaseMoveAnimation : DoubleAnimationBase
{
public static readonly DependencyProperty FromProperty = DependencyProperty.Register(
"From", typeof(double?), typeof(EaseMoveAnimation), new PropertyMetadata(null));
public static readonly DependencyProperty ToProperty = DependencyProperty.Register(
"To", typeof(double?), typeof(EaseMoveAnimation), new PropertyMetadata(null));
public static readonly DependencyProperty PowerProperty = DependencyProperty.Register(
"Power", typeof(double?), typeof(EaseMoveAnimation), new PropertyMetadata(null));
public double? From
{
get
{
return (double?)this.GetValue(EaseMoveAnimation.FromProperty);
}
set
{
this.SetValue(EaseMoveAnimation.FromProperty, value);
}
}
public double? To
{
get
{
return (double?)this.GetValue(EaseMoveAnimation.ToProperty);
}
set
{
this.SetValue(EaseMoveAnimation.ToProperty, value);
}
}
/// <summary>
/// 幂指数,值越大,曲线上点的斜率越大,加速度越大,设置为5时效果较好
/// </summary>
public double? Power
{
get
{
return (double?)this.GetValue(EaseMoveAnimation.PowerProperty);
}
set
{
this.SetValue(EaseMoveAnimation.PowerProperty, value);
}
}
protected override double GetCurrentValueCore(double defaultOriginValue, double defaultDestinationValue, AnimationClock animationClock)
{
double from = (this.From==null?defaultDestinationValue:(double)this.From);
double to = (this.To==null?defaultOriginValue:(double)this.To);
double delta = to - from;
double power = this.Power == null ? 2 : (double)this.Power;
//加速
return delta * Math.Pow(animationClock.CurrentProgress.Value, power) + from;
//return delta * Math.Pow(animationClock.CurrentProgress.Value, 1/power) + from;
}
protected override System.Windows.Freezable CreateInstanceCore()
{
return new EaseMoveAnimation();
}
}
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : System.Windows.Window
{
public Window1()
{
InitializeComponent();
this.button1.Click += new RoutedEventHandler(button1_Click);
this.button2.Click += new RoutedEventHandler(button2_Click);
}
void button2_Click(object sender, RoutedEventArgs e)
{
IniTest();
}
void button1_Click(object sender, RoutedEventArgs e)
{
IniTest();
}
private void IniTest()
{
EaseMoveAnimation animation1 = new EaseMoveAnimation();
animation1.From = 0;
animation1.To = 1000;
animation1.Duration = TimeSpan.FromSeconds(2);
animation1.Power = 5;
this.button1.BeginAnimation(Canvas.LeftProperty, animation1);
DoubleAnimation animation2 = new DoubleAnimation();
animation2.From = animation1.From;
animation2.To = animation1.To;
animation2.Duration = animation1.Duration;
this.button2.BeginAnimation(Canvas.LeftProperty, animation2);
}
}