动画基础,3种动画方式

Posted 莫欺

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动画基础,3种动画方式相关的知识,希望对你有一定的参考价值。

WPF编程学习——动画

WPF中的动画——(一)基本概念

WPF中的动画——(二)From/To/By 动画

WPF中的动画——(三)时间线(TimeLine)

WPF中的动画——(四)缓动函数

WPF中的动画——(五)关键帧动画

 

 线性插值动画类 适合单个动画,若要在两个以上的目标值之间使用其他内插方法或者进行动画处理,请使用 DoubleAnimationUsingKeyFrames 对象。

 

本文将介绍WPF 中三种基本动画,线性插值、关键帧和路径动画。

  在 System.Windows.Media.Animation 这个命名空间中,包含了三种动画类:线性插值动画类(17个,简单单个动画)、关键帧动画(22个,几个动画组合起来的复杂动画)、路径动画(3个)。

  在C#代码中使用Animation类,需要引入命名空间:System.Windows.Media.Animation

  using System.Windows.Media.Animation;

1、线性插值动画

  该动画表现为,元素的某个属性,在开始值和结束值之间逐步增加,是一种线性插值的过程。比如,实现一个按钮的淡入效果,让它的透明度Opacity在0~1之间线性增长,就可以实现预期效果。 

  以下是 System.Windows.Media.Animation 命名空间中,17个线性插值动画类。  

ByteAnimation

ColorAnimation

DecimalAnimation

DoubleAnimation

Int16Animation

Int32Animation

Int64Animation

Point3DAnimation

PointAnimation

QuaternionAnimation

RectAnimation

Rotation3DAnimation

SingleAnimation

SizeAnimation

ThicknessAnimation

Vector3DAnimation

VectorAnimation

示例1:以 DoubleAnimation 为例,实现文字的淡入效果。

  在XAML中可以直接定义动画,以下示例是以后台代码形式实现的动画。

  XAML

<TextBlock Height="50" Width="220" Foreground="#326939" FontSize="36" Name="textBlock1" Text="文字淡入效果"/>

  CS  

DoubleAnimation da = new DoubleAnimation();
da.From = 0;    //起始值
da.To = 1;      //结束值
da.Duration = TimeSpan.FromSeconds(3);         //动画持续时间
this.textBlock1.BeginAnimation(TextBlock.OpacityProperty, da);//开始动画

 

 

<StackPanel>
    <StackPanel.Resources>
        <Storyboard x:Name="myStoryboard">
            <DoubleAnimation
          Storyboard.TargetName="MyAnimatedRectangle"
          Storyboard.TargetProperty="Opacity"
          From="1.0" To="0.0" Duration="0:0:5" 
          AutoReverse="True" RepeatBehavior="Forever" />
        </Storyboard>
    </StackPanel.Resources>

    <Rectangle Loaded="Start_Animation" x:Name="MyAnimatedRectangle"
     Width="100" Height="100" Fill="Blue" />

</StackPanel>

 

  

示例2:利用 ThicknessAnimation ,实现元素平移效果。

  XMAL

<TextBlock Height="50" Foreground="#326939" Margin="0,100,0,0" FontSize="36" Name="textBlock1" Text="文字平移"/>

  CS

//文字平移,Margin属性是Thickness类型,选择ThicknessAnimation
ThicknessAnimation ta = new ThicknessAnimation();
ta.From = new Thickness(0, 100, 0, 0);             //起始值
ta.To = new Thickness(240, 100, 0, 0);        //结束值
ta.Duration = TimeSpan.FromSeconds(3);         //动画持续时间
this.textBlock1.BeginAnimation(TextBlock.MarginProperty, ta);//开始动画



2、关键帧动画

  关键帧动画是以时间为节点,在指定时间节点上,属性达到某个值。

  以下是 System.Windows.Media.Animation 命名空间中,22个关键帧动画类。  

BooleanAnimationUsingKeyFrames

ByteAnimationUsingKeyFrames

CharAnimationUsingKeyFrames

ColorAnimationUsingKeyFrames

DecimalAnimationUsingKeyFrames

DoubleAnimationUsingKeyFrames

Int16AnimationUsingKeyFrames

Int32AnimationUsingKeyFrames

Int64AnimationUsingKeyFrames

MatrixAnimationUsingKeyFrames

ObjectAnimationUsingKeyFrames

Point3DAnimationUsingKeyFrames

PointAnimationUsingKeyFrames

QuaternionAnimationUsingKeyFrames

RectAnimationUsingKeyFrames

Rotation3DAnimationUsingKeyFrames

SingleAnimationUsingKeyFrames

SizeAnimationUsingKeyFrames

StringAnimationUsingKeyFrames

ThicknessAnimationUsingKeyFrames

Vector3DAnimationUsingKeyFrames

VectorAnimationUsingKeyFrames

示例3:Border宽度的关键帧动画

XAML

<Border Height="32" Width="0" Background="#326939"  Name="border1"/>

CS

复制代码
//Border长度关键帧动画
DoubleAnimationUsingKeyFrames dak = new DoubleAnimationUsingKeyFrames();
//关键帧定义
dak.KeyFrames.Add(new LinearDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0))));
dak.KeyFrames.Add(new LinearDoubleKeyFrame(240, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(3))));
dak.KeyFrames.Add(new LinearDoubleKeyFrame(240, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(6))));
dak.KeyFrames.Add(new LinearDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(9))));
            
dak.BeginTime = TimeSpan.FromSeconds(2);//从第2秒开始动画
dak.RepeatBehavior = new RepeatBehavior(3);//动画重复3次
//开始动画
this.border1.BeginAnimation(Border.WidthProperty, dak);
复制代码

  (程序运行时开始计时,第0秒)

  0~5:动画尚未开始;

  5~8:border1宽度从0增加到240;

  8~11:border1宽度保持240不变;

  11~14:border1宽度从240减少到0;

  14-17:又从0增加到240……(即5~14的过程循环3次)

3、路径动画

  基于路径的动画,比起前两种更加专业一些。它的表现方式是,修改数值使其符合PathGeometry对象描述的形状,并且让元素沿着路径移动。以下是 System.Windows.Media.Animation 命名空间中,3个路径动画类。

DoubleAnimationUsingPath

MatrixAnimationUsingPath

PointAnimationUsingPath

示例4:基于路径动画的演示

XMAL(该动画是在XAML中定义,使用事件触发器,窗体加载时开始动画)

复制代码
<Window x:Class="WpfApplication9.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="360" Width="480">
    <Window.Resources>
        <!--路径资源-->
        <PathGeometry x:Key="path">
            <PathFigure IsClosed="True">
                <ArcSegment Point="200,200" Size="30,10" SweepDirection="Clockwise"></ArcSegment>
                <ArcSegment Point="300,200" Size="5,5"></ArcSegment>
            </PathFigure>
        </PathGeometry>
    </Window.Resources>
    <!---事件触发器,窗体加载时动画开始,周期6秒,无限循环-->
    <Window.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimationUsingPath Storyboard.TargetName="image" Storyboard.TargetProperty="(Canvas.Left)"
                     PathGeometry="{StaticResource path}" Duration="0:0:6" RepeatBehavior="Forever" Source="X"></DoubleAnimationUsingPath>
                    <DoubleAnimationUsingPath Storyboard.TargetName="image" Storyboard.TargetProperty="(Canvas.Top)"
                     PathGeometry="{StaticResource path}" Duration="0:0:6" RepeatBehavior="Forever" Source="Y"></DoubleAnimationUsingPath>
                </Storyboard>                
            </BeginStoryboard>
        </EventTrigger>
    </Window.Triggers>
    <Canvas>
        <!--显示路径-->
        <Path Margin="30" Stroke="#ddd" Data="{StaticResource path}"></Path>
        <!--动画元素-->
        <Image Name="image" Source="me.png" Width="48" Height="48" />
    </Canvas>
</Window>
复制代码

  我的头像将沿着曲线路径进行移动,由于RepeatBehavior属性设置为Forever,则动画将无限循环。

 

 Storyboard animationTab = new Storyboard();
               DoubleAnimationUsingKeyFrames da1 = new DoubleAnimationUsingKeyFrames();
               Storyboard.SetTarget(da1, gridA);
               Storyboard.SetTargetProperty(da1, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"));
               EasingDoubleKeyFrame edk1_1 = new EasingDoubleKeyFrame();
               edk1_1.KeyTime = TimeSpan.FromSeconds(0.5);
               edk1_1.Value = zoomNum;
               da1.KeyFrames.Add(edk1_1);
               EasingDoubleKeyFrame edk1_2 = new EasingDoubleKeyFrame();
               edk1_2.KeyTime = TimeSpan.FromSeconds(1);
               edk1_2.Value = narrowNum;
               // edk1_2.EasingFunction = new QuinticEase() { EasingMode = EasingMode.EaseOut };
               da1.KeyFrames.Add(edk1_2);

               animationTab.Children.Add(da1);

               DoubleAnimationUsingKeyFrames da2 = new DoubleAnimationUsingKeyFrames();
               Storyboard.SetTarget(da2, gridA);
               Storyboard.SetTargetProperty(da2, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"));
               EasingDoubleKeyFrame edk2_1 = new EasingDoubleKeyFrame();
               edk2_1.KeyTime = TimeSpan.FromSeconds(0.5);
               edk2_1.Value = zoomNum;
               da2.KeyFrames.Add(edk2_1);
               EasingDoubleKeyFrame edk2_2 = new EasingDoubleKeyFrame();
               edk2_2.KeyTime = TimeSpan.FromSeconds(1);
               edk2_2.Value = narrowNum;
               //edk2_2.EasingFunction = new QuinticEase() { EasingMode = EasingMode.EaseOut };
               da2.KeyFrames.Add(edk2_2);
               animationTab.Children.Add(da2);

               DoubleAnimationUsingKeyFrames da3 = new DoubleAnimationUsingKeyFrames();
               Storyboard.SetTarget(da3, gridA);
               Storyboard.SetTargetProperty(da3, new PropertyPath("(Canvas.Left)"));
               EasingDoubleKeyFrame edk3_1 = new EasingDoubleKeyFrame();
               edk3_1.KeyTime = TimeSpan.FromSeconds(0.5);
               edk3_1.Value = (double)gridA.GetValue(Canvas.LeftProperty);
               da3.KeyFrames.Add(edk3_1);
               EasingDoubleKeyFrame edk3_2 = new EasingDoubleKeyFrame();
               edk3_2.KeyTime = TimeSpan.FromSeconds(1.5);
               edk3_2.Value = ttfX;
               da3.KeyFrames.Add(edk3_2);
               animationTab.Children.Add(da3);

               DoubleAnimationUsingKeyFrames da4 = new DoubleAnimationUsingKeyFrames();
               Storyboard.SetTarget(da4, gridA);
               Storyboard.SetTargetProperty(da4, new PropertyPath("(Canvas.Top)"));
               EasingDoubleKeyFrame edk4_1 = new EasingDoubleKeyFrame();
               edk4_1.KeyTime = TimeSpan.FromSeconds(0.5);
               edk4_1.Value = (double)gridA.GetValue(Canvas.TopProperty);
               da4.KeyFrames.Add(edk4_1);
               EasingDoubleKeyFrame edk4_2 = new EasingDoubleKeyFrame();
               edk4_2.KeyTime = TimeSpan.FromSeconds(1.5);
               edk4_2.Value = ttfY;
               da4.KeyFrames.Add(edk4_2);
               animationTab.Children.Add(da4);

               DoubleAnimationUsingKeyFrames da5 = new DoubleAnimationUsingKeyFrames();
               Storyboard.SetTarget(da5, gridA);
               Storyboard.SetTargetProperty(da5, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"));
               EasingDoubleKeyFrame edk5_1 = new EasingDoubleKeyFrame();
               edk5_1.KeyTime = TimeSpan.FromSeconds(0.5);
               edk5_1.Value = 0;
               da5.KeyFrames.Add(edk5_1);
               EasingDoubleKeyFrame edk5_2 = new EasingDoubleKeyFrame();
               edk5_2.KeyTime = TimeSpan.FromSeconds(1.5);
               edk5_2.Value = 180;
               da5.KeyFrames.Add(edk5_2);
               animationTab.Children.Add(da5);

               PointAnimationUsingKeyFrames da6 = new PointAnimationUsingKeyFrames();
               Storyboard.SetTarget(da6, gridA);
               Storyboard.SetTargetProperty(da6, new PropertyPath("(UIElement.RenderTransformOrigin)"));
               EasingPointKeyFrame edk6_1 = new EasingPointKeyFrame();
               edk6_1.KeyTime = TimeSpan.FromSeconds(0.5);
               edk6_1.Value = new Point(0.5, 0.5);
               da6.KeyFrames.Add(edk6_1);
               EasingPointKeyFrame edk6_2 = new EasingPointKeyFrame();
               edk6_2.KeyTime = TimeSpan.FromSeconds(1);
               edk6_2.Value = new Point(0, 0);
               da6.KeyFrames.Add(edk6_2);
               animationTab.Children.Add(da6);

               animationTab.Completed += (o, e) =>
               {
                   animationTab.Stop();
                   gridA.Visibility = Visibility.Collapsed;
                  mWindow.canvasSB.Children.Remove(gridA);
                   if (aEnum != AnimationFlyEnum.None)
                       buttonAnimationAddOne(aEnum, horSet);
                   if (ac != null)
                       ac.Invoke();
               };
               animationTab.Begin();

 

以上是关于动画基础,3种动画方式的主要内容,如果未能解决你的问题,请参考以下文章

css 动画实现的 3 种方式

VSCode自定义代码片段——CSS动画

VSCode自定义代码片段7——CSS动画

VSCode自定义代码片段7——CSS动画

Android 动画布局和视图

cocos creator基础-(十六)自定义的帧动画播放组件(需要优化)