1,Animation类:
DoubleAnimation widthAnimation = new DoubleAnimation(); widthAnimation.To = this.Width - 30; widthAnimation.Duration = TimeSpan.FromSeconds(5); widthAnimation.Completed += animation_Completed; DoubleAnimation heightAnimation = new DoubleAnimation(); heightAnimation.To = (this.Height - 50)/3; heightAnimation.Duration = TimeSpan.FromSeconds(5); cmdGrow.BeginAnimation(Button.WidthProperty, widthAnimation); cmdGrow.BeginAnimation(Button.HeightProperty, heightAnimation); }
创建类,并且设定其两个值.---注意,动画类的最后的值并不会还原.
--------当忽略From时,将从当前值到To值
-----------当忽略了to时,将从当前值到依赖性的期待值.
DoubleAnimation widthAnimation = new DoubleAnimation(); widthAnimation.Duration = TimeSpan.FromSeconds(5); DoubleAnimation heightAnimation = new DoubleAnimation(); heightAnimation.Duration = TimeSpan.FromSeconds(5); cmdGrow.BeginAnimation(Button.WidthProperty, widthAnimation); cmdGrow.BeginAnimation(Button.HeightProperty, heightAnimation);
-------------By...定义增大量.
DoubleAnimation widthAnimation = new DoubleAnimation();
widthAnimation.By = 10;
widthAnimation.Duration = TimeSpan.FromSeconds(0.5);
cmdGrowIncrementally.BeginAnimation(Button.WidthProperty, widthAnimation);
Duration---对象:设定动画动作间隔
Duration可以和TimeSpan进行转换.并且设定了两个值
Duration.Automatic---持续1秒 Duration.Forever---永远不动
如何还原对象之前的值:
AutoReverse属性=true的动画,在执行到指定值之后会继续进行反向动画直到还原.
FillBehavior=Stop,在执行完动画后自动返回.
Duration=Duration.Forever则不执行动画.
使用 如下方法可以删除动画.
cmdGrow.BeginAnimation(Button.WidthProperty, null);
二 ,TimeLine抽象类的属性:
RepeatBehavior:
1,通过次数重复动画: new RepeatBehavior(2)
2,通过事件重复动画:new RepeatBehavior(5)--重复2次半
3,设定IsCumulative;表明在重复的时候,是否从当前动画值开始.
4,不断重复动画.RepeatBehavior.Forever.
三,故事板------在XAML中创建动画
1,创建故事板对象
2,创建触发器
<Button.Triggers> <EventTrigger RoutedEvent="Button.Click"> <EventTrigger.Actions> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetProperty="Width" To="{Binding ElementName=window,Path=Width,Converter={StaticResource converter},ConverterParameter=-30}" Duration="0:0:5"></DoubleAnimation> <DoubleAnimation Storyboard.TargetProperty="Height" To="{Binding ElementName=window,Path=Height,Converter={StaticResource converter},ConverterParameter=-50}" Duration="0:0:5"></DoubleAnimation> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> </Button.Triggers>
------------------使用Convert将String类型转换到需要类型
public class ArithmeticConverter : IValueConverter { private const string ArithmeticParseExpression = "([+\-*/]{1,1})\s{0,}(\-?[\d\.]+)"; private Regex arithmeticRegex = new Regex(ArithmeticParseExpression); public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (value is double && parameter != null) { string param = parameter.ToString(); if (param.Length > 0) { Match match = arithmeticRegex.Match(param); if (match != null && match.Groups.Count == 3) { string operation = match.Groups[1].Value.Trim(); string numericValue = match.Groups[2].Value; double number = 0; if (double.TryParse(numericValue, out number)) // this should always succeed or our regex is broken { double valueAsDouble = (double)value; double returnValue = 0; switch (operation) { case "+": returnValue = valueAsDouble + number; break; case "-": returnValue = valueAsDouble - number; break; case "*": returnValue = valueAsDouble * number; break; case "/": returnValue = valueAsDouble / number; break; } return returnValue; } } } } return null; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new Exception("The method or operation is not implemented."); } }
使用触发器进行触发:
<Style TargetType="ListBoxItem"> <Style.Setters> <Setter Property="FontSize" Value="30"/> </Style.Setters> <Style.Triggers> <EventTrigger RoutedEvent="ListBoxItem.MouseEnter"> <EventTrigger.Actions> <BeginStoryboard > <Storyboard> <DoubleAnimation Storyboard.TargetProperty="FontSize" BeginTime="0:0:0.1" Duration="0:0:0.2" To="40"></DoubleAnimation> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> <EventTrigger RoutedEvent="ListBoxItem.MouseLeave"> <EventTrigger.Actions> <BeginStoryboard > <Storyboard> <DoubleAnimation Storyboard.TargetProperty="FontSize" BeginTime="0:0:0.1" Duration="0:0:0.2" ></DoubleAnimation> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> </Style.Triggers> </Style>
四,控制动画---
制作界面:
1,界面元素:
5个按钮,对应Storyboard的效果:
<EventTrigger SourceName="cmdStart" RoutedEvent="Button.Click"> <BeginStoryboard Name="fadeStoryboardBegin"> <!-- The SpeedRatio binding makes sure the initial speed matches the slider. The Slider's event handling code makes sure the speed is updated when the slider is moved. --> <Storyboard Name="fadeStoryboard" CurrentTimeInvalidated="storyboard_CurrentTimeInvalidated" SpeedRatio="{Binding ElementName=sldSpeed,Path=Value}"> <DoubleAnimation Storyboard.TargetName="imgDay" Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:10" RepeatBehavior="Forever" Completed="DoubleAnimation_Completed" ></DoubleAnimation> </Storyboard> </BeginStoryboard> </EventTrigger> <EventTrigger SourceName="cmdPause" RoutedEvent="Button.Click"> <PauseStoryboard BeginStoryboardName="fadeStoryboardBegin"></PauseStoryboard> </EventTrigger> <EventTrigger SourceName="cmdResume" RoutedEvent="Button.Click"> <ResumeStoryboard BeginStoryboardName="fadeStoryboardBegin"></ResumeStoryboard> </EventTrigger> <EventTrigger SourceName="cmdStop" RoutedEvent="Button.Click"> <StopStoryboard BeginStoryboardName="fadeStoryboardBegin"></StopStoryboard> </EventTrigger> <EventTrigger SourceName="cmdMiddle" RoutedEvent="Button.Click"> <SeekStoryboard BeginStoryboardName="fadeStoryboardBegin" Offset="0:0:5"></SeekStoryboard> </EventTrigger>
使用这个画刷进行更新画面
<Grid> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> </Grid.RowDefinitions> <Grid> <Image Source="night.jpg"></Image> <Image Source="day.jpg" Name="imgDay"> <Image.OpacityMask> <LinearGradientBrush StartPoint="0,0" EndPoint="1,0.2"> <GradientStop Offset="0" Color="Transparent" x:Name="transparentStop" /> <GradientStop Offset="0" Color="Black" x:Name="visibleStop" /> </LinearGradientBrush> </Image.OpacityMask> </Image> </Grid> <Button Name="cmdStart" Grid.Row="1" Padding="5" Margin="5"> Start <Button.Triggers> <EventTrigger SourceName="cmdStart" RoutedEvent="Button.Click"> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetName="transparentStop" Storyboard.TargetProperty="Offset" BeginTime="0:0:0.2" From="0" To="1" Duration="0:0:1" ></DoubleAnimation> <DoubleAnimation Storyboard.TargetName="visibleStop" Storyboard.TargetProperty="Offset" From="0" To="1.2" Duration="0:0:1.2" ></DoubleAnimation> </Storyboard> </BeginStoryboard> </EventTrigger> </Button.Triggers> </Button> </Grid>
4,通过事件更新信息:
private void storyboard_CurrentTimeInvalidated(object sender, EventArgs e) { // Sender is the clock that was created for this storyboard. Clock storyboardClock = (Clock)sender; if (storyboardClock.CurrentProgress == null) { lblTime.Text = "[[ stopped ]]"; progressBar.Value = 0; } else { lblTime.Text = storyboardClock.CurrentTime.ToString(); progressBar.Value = (double)storyboardClock.CurrentProgress; } }
五,缓动函数:
<Storyboard> <DoubleAnimation Storyboard.TargetName="cmdGrow" Storyboard.TargetProperty="Width" To="400" Duration="0:0:1.5"> <DoubleAnimation.EasingFunction> <ElasticEase EasingMode="EaseInOut" Oscillations="10" ></ElasticEase> </DoubleAnimation.EasingFunction> </DoubleAnimation> </Storyboard>
EasingMode:In,Out,InOut时候是效果不同的.
创建自定义函数:
public class RandomJitterEase : EasingFunctionBase { // Store a random number generator. private Random rand = new Random(); protected override double EaseInCore(double normalizedTime) { //To see the values add code like this: //System.Diagnostics.Debug.WriteLine(...); // Make sure there's no jitter in the final value. if (normalizedTime == 1) return 1; // Offset the value by a random amount. return Math.Abs(normalizedTime - (double)rand.Next(0,10)/(2010 - Jitter)); } public int Jitter { get { return (int)GetValue(JitterProperty); } set { SetValue(JitterProperty, value); } } public static readonly DependencyProperty JitterProperty = DependencyProperty.Register("Jitter", typeof(int), typeof(RandomJitterEase), new UIPropertyMetadata(1000), new ValidateValueCallback(ValidateJitter)); private static bool ValidateJitter(object value) { int jitterValue = (int)value; return ((jitterValue <= 2000) && (jitterValue >= 0)); } // This required override simply provides a live instance of your easing function. protected override Freezable CreateInstanceCore() { return new RandomJitterEase(); }
1,创建一个EasingFunctionBase 的派生类.
添加新的依赖性属性Jitter.
重写EaseInCore和CreateInstanceCore()函数.
然后,在xaml中进行引用.
xmlns:local="clr-namespace:Animation">
6,动画速率
<BeginStoryboard x:Key="beginStoryboard"> <Storyboard Timeline.DesiredFrameRate="{Binding ElementName=txtFrameRate,Path=Text}"> <DoubleAnimation Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(Canvas.Left)" From="0" To="300" Duration="0:0:5"> </DoubleAnimation> <DoubleAnimation Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(Canvas.Top)" From="300" To="0" AutoReverse="True" Duration="0:0:2.5" DecelerationRatio="1"> </DoubleAnimation> </Storyboard> </BeginStoryboard>
7,位图缓存:
PathGeometry pathGeometry = new PathGeometry(); PathFigure pathFigure = new PathFigure(); pathFigure.StartPoint = new Point(0,0); PathSegmentCollection pathSegmentCollection = new PathSegmentCollection(); int maxHeight = (int)this.Height; int maxWidth = (int)this.Width; Random rand = new Random(); for (int i = 0; i < 500; i++) { LineSegment newSegment = new LineSegment(); newSegment.Point = new Point(rand.Next(0, maxWidth), rand.Next(0, maxHeight)); pathSegmentCollection.Add(newSegment); } pathFigure.Segments = pathSegmentCollection; pathGeometry.Figures.Add(pathFigure); pathBackground.Data = pathGeometry;
使用代码创建背景
private void chkCache_Click(object sender, RoutedEventArgs e) { if (chkCache.IsChecked == true) { BitmapCache bitmapCache = new BitmapCache(); pathBackground.CacheMode = new BitmapCache(); } else { pathBackground.CacheMode = null; } }