zoukankan      html  css  js  c++  java
  • WPF 动画笔记

    Demo在这里 https://files.cnblogs.com/xiaokang088/WpfAnimation.zip

    1. Animation结构

    以DoubleAnimation 来看结构,如下:

    System. Object
    System.Windows.Threading. DispatcherObject
    System.Windows. DependencyObject
    System.Windows. Freezable
    System.Windows.Media.Animation. Animatable
    System.Windows.Media.Animation. Timeline
    System.Windows.Media.Animation. AnimationTimeline
    System.Windows.Media.Animation. DoubleAnimationBase
    System.Windows.Media.Animation. DoubleAnimation
    System.Windows.Media.Animation. DoubleAnimationUsingKeyFrames
    System.Windows.Media.Animation. DoubleAnimationUsingPath

    DoubleAnimtionBase以下有三种动画类型

    最常用的是DoubleAnimation,最熟悉的了。

    其次是DoubleAnimtionUsingKeyFrames,这个最丰富,他的KeyFrams能够接受三种类型的KeyFrame,分别是离散、线性、样条,后面详述。

    最后是DoubleAnimtionUsingPath,这个最有意思,可以沿着一个指定的轨迹来进行动画,最好玩的是MatrixAnimtionUsingPath。

    DoubleAnimtionBase 是Double类动画的一个基础类,如果要自定义一个Double动画,可以继承DoubleAnimtionBase来写,如下,其中GetCurrentValueCore和CreateInstanceCore是一定要重写的。

    public class TestAnimation : DoubleAnimationBase
     {
            public static readonly DependencyProperty FromProperty = DependencyProperty.Register("From", typeof(double?), typeof(TestAnimation));
            public double? From
            {
                get { return (double?)GetValue(FromProperty); }
                set { SetValue(FromProperty, value); }
            }
            public static readonly DependencyProperty ToProperty = DependencyProperty.Register("To", typeof(double?), typeof(TestAnimation))
            public double? To
            {
                get { return (double?)GetValue(ToProperty); }
                set { SetValue(ToProperty, value); }
            }
    
            public static readonly DependencyProperty IntervalProperty = DependencyProperty.Register("Interval", typeof(double?), typeof(TestAnimation))
            public double? Interval
            {
                get { return (double?)GetValue(IntervalProperty); }
                set { SetValue(IntervalProperty, value); }
            }
    
            protected override double GetCurrentValueCore(double defaultOriginValue, double defaultDestinationValue, AnimationClock animationClock)
            {
                double returnValue;
                double from = 0, delta = 0;
    
                from = From.HasValue ? From.Value : defaultOriginValue;
                delta = To.HasValue ? To.Value - from : defaultDestinationValue - from;
    
    
                returnValue = (int)(animationClock.CurrentProgress.Value * delta / 30) * 30 + from;
                if (animationClock.CurrentProgress.Value == 1)
                    returnValue = from + delta;
                return returnValue;
            }
    
            protected override Freezable CreateInstanceCore()
            {
                return new TestAnimation();
            }
        }
    

    往上看

    AnimationTimeline,这个是Animtion的鼻祖了,提供了多个对动画来说很重要的方法,如下:

            public AnimationClock CreateClock();

            public virtual object GetCurrentValue(object defaultOriginValue, object defaultDestinationValue, AnimationClock animationClock);

      关于CreateClock,据说,用clock的效率会比较高,如下代码:

        AnimationClock myClock = myAnimation.CreateClock();
                //1.据说这样写效率比较高
                myScaleTransform.ApplyAnimationClock(
                    ScaleTransform.ScaleXProperty, myClock);
                myScaleTransform.ApplyAnimationClock(
                    ScaleTransform.ScaleYProperty, myClock);
    
                //myScaleTransform.BeginAnimation(ScaleTransform.ScaleXProperty, myAnimation);
    
                //myScaleTransform.BeginAnimation(ScaleTransform.ScaleYProperty, myAnimation);
    

    Timeline,动画进行的基础,这些动画都是基于时间轴进行的,所以提供了很多基础的成员,例如属性:

         public double AccelerationRatio { get; set; }
            public bool AutoReverse { get; set; }
            public TimeSpan? BeginTime { get; set; }
            public double DecelerationRatio { get; set; }
            public Duration Duration { get; set; }
            public FillBehavior FillBehavior { get; set; }
            public RepeatBehavior RepeatBehavior { get; set; }
            public double SpeedRatio { get; set; }
    
    2.接上详细阐述DoubleAnimtionUsingKeyFrames

    看例子:

     

    <Storyboard  >
    <DoubleAnimationUsingKeyFrames
                      Storyboard.TargetName="myRectangle"
                      Storyboard.TargetProperty="(Canvas.Left)">
    <LinearDoubleKeyFrame Value="500" KeyTime="0:0:3" />
    <DiscreteDoubleKeyFrame Value="400" KeyTime="0:0:4" />
    <SplineDoubleKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="10" KeyTime="0:0:6" />
    </DoubleAnimationUsingKeyFrames>
    </Storyboard>
    

    LinearDoubleKeyFrame 线性动画,3秒钟后到left=500,匀速移动到500的位置

    DiscreteDoubleKeyFrame 离散动画,接上一个动画,4秒的时候突然蹦到400的位置

    SplineDoubleKeyFrame 样条动画,这个最复杂了,6秒后到达10的位置。

    若要了解 KeySpline 的工作原理,首先需要了解三次方贝塞尔曲线。 一条三次方贝塞尔曲线由一个起点、一个终点和两个控制点来定义。KeySpline 中的两个坐标定义了这两个控制点。 在描述关键样条时,贝塞尔曲线的起点始终为 0,终点始终为 1,这也就是只定义两个控制点的原因。得到的曲线指定了如何在一个时间段内内插动画;也就是说,该曲线表示动画的目标属性在该时间段内的变化速度。为了更好地了解动画进度与贝塞尔曲线之间的关系,请参见 Key Spline Animation Sample(关键样条动画示例http://msdn.microsoft.com/zh-cn/library/ms771640(VS.85).aspx)。

    附件Demo里面也有例子,请仔细看。

    另外,KeyTime也是很有讲究的,

        <LinearDoubleKeyFrame Value="400" KeyTime="00:00:04" />

    为普通的计时方式,00:00:04即为本段动画时间为4秒

          <LinearDoubleKeyFrame Value="100" KeyTime="10%" />

    10%代表本段动画耗时占全部时间的10%

       <LinearDoubleKeyFrame Value="100" KeyTime="Uniform" />

    所有KeyFrame耗时都是一样的

        <LinearDoubleKeyFrame Value="100" KeyTime="Paced" />

    所有KeyFrame都是匀速的,个人觉得这个很鸡肋。

    详见Demo

    3.接上,阐述MatrixAnimationUsingPath

    让元素沿着轨迹走,而且DoesRotateWithTangent=True可以控制元素朝着轨迹的方向。

         <Button Width="50" Height="50" Canvas.Left="10" Canvas.Top="10"  RenderTransformOrigin=".5,.5">
    
                <Button.RenderTransform>
    
                    <MatrixTransform x:Name="myMatrix" >
    
                        <MatrixTransform.Matrix>
    
                            <Matrix />
    
                        </MatrixTransform.Matrix>
    
                    </MatrixTransform>
    
                </Button.RenderTransform>
    
                <Button.Triggers>
    
                    <EventTrigger RoutedEvent="Button.Click">
    
                        <BeginStoryboard>
    
                            <Storyboard>
    
                                <MatrixAnimationUsingPath Storyboard.TargetName="myMatrix" Storyboard.TargetProperty="Matrix"
    
                                                      Duration="00:00:5"   DoesRotateWithTangent="True" >
    
                                    <MatrixAnimationUsingPath.PathGeometry>
    
                                        <PathGeometry>
    
                                            <PathFigure>
    
                                                <BezierSegment Point1="35,310" Point2="610,35" Point3="610,310" />
    
                                            </PathFigure>
    
                                        </PathGeometry>
    
                                    </MatrixAnimationUsingPath.PathGeometry>
    
                                </MatrixAnimationUsingPath>
    
                            </Storyboard>
    
                        </BeginStoryboard>
    
                    </EventTrigger>
    
                </Button.Triggers>
    
            </Button>
    

    4.关注比较少的属性

    By 以往只注意了From、To ,起始值和终止值,By可以获取或设置动画更改其起始值时依据的总量。如果同时设置了 To 和 By 属性,则 To 属性优先,而 By 属性会被忽略。

    IsAdditve:获取或设置一个值,该值指示是否应将目标属性的当前值与此动画的起始值相加。如果动画仅设置了其 From、 To 或 By 属性之一,则设置此属性将无效。

    IsCumulative 获取或设置动画更改其起始值时依据的总量。如果同时设置了 To 和 By 属性,则 To 属性优先,而 By 属性会被忽略。

    5.关于StoryBoard,先看继承结构

     

    System. Object
    System.Windows.Threading. DispatcherObject
    System.Windows. DependencyObject
    System.Windows. Freezable
    System.Windows.Media.Animation. Animatable
    System.Windows.Media.Animation. Timeline
    System.Windows.Media.Animation. TimelineGroup
    System.Windows.Media.Animation. ParallelTimeline
    System.Windows.Media.Animation. Storyboard

    Storyboard 继承与ParallelTimeline,那么ParallelTimeline是个什么东西呢?看例子:

     

      <Canvas.Triggers>
                <EventTrigger RoutedEvent="Button.Click" SourceName="button1">
                    <BeginStoryboard>
                        <Storyboard>
                            <!-- "ParallelTimelines are..." fades into view. -->
                            <DoubleAnimation Storyboard.TargetName="FirstTextBlock"
                  Storyboard.TargetProperty="Opacity" Duration="0:0:2" From="0" To="1" />
                            <!-- "ParallelTimelines are..." skews to the left. -->
                            <DoubleAnimation Storyboard.TargetName="FirstTextBlockSkew"
                  Storyboard.TargetProperty="AngleX" Duration="0:0:2" BeginTime="0:0:2" From="0" To="45" />
                            <!-- This ParallelTimeline contains all the animations for the TextBlock with the text
                  "Useful" in it. This ParallelTimeline begins 4 seconds after the Storyboard timeline begins and all child
                  animations begin relative to this parent timeline. -->
                            <ParallelTimeline BeginTime="0:0:4">
                                <!-- "Useful" fades into view. -->
                                <DoubleAnimation Storyboard.TargetName="SecondTextBlock"
                    Storyboard.TargetProperty="Opacity" Duration="0:0:2" From="0" To="1" />
                                <!-- "Useful" slides in from the right. -->
                                <DoubleAnimation Storyboard.TargetName="SecondTextBlockSkew"
                    Storyboard.TargetProperty="AngleX" Duration="0:0:2" From="90" To="180" />
                                <!-- "Useful" skews to the right. -->
                                <DoubleAnimation Storyboard.TargetName="SecondTextBlockSkew"
                    Storyboard.TargetProperty="AngleX" BeginTime="0:0:3" Duration="0:0:0.2" From="0" To="-60" />
                                <!-- "Useful" Gets taller. -->
                                <DoubleAnimation Storyboard.TargetName="SecondTextBlockScale"
                    Storyboard.TargetProperty="ScaleY" BeginTime="0:0:3" Duration="0:0:0.2" From="1" To="3" />
                            </ParallelTimeline>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Canvas.Triggers>
    

    ParallelTimeline 把几个动画放到一起,可以控制开始时间。

    StoryBoard在继承了ParallelTimeline后,增加了一个常用的操作,例如Begin/Stop/Pause等操作和TargetProperty等属性

  • 相关阅读:
    学习笔记::有上下界的网络流
    zoj2314
    bzoj3261
    bzoj 1898
    bzoj4009
    bzoj4033
    bzoj3389
    bzoj2427
    uva 11825
    交换A与B值的四种方法
  • 原文地址:https://www.cnblogs.com/xiaokang088/p/2051101.html
Copyright © 2011-2022 走看看