• Silverlight中的动画详解(仅常见问题以及疑难杂症)


    此文旨在指出在silverlight动画中出现的问题:

    一、当设置完动画即(StoryBoard.Begin()或者加载动画完毕后)后无法设置目标对象属性的值。

    标题可能有点绕口,看下下面的代码即可明白:

                Storyboard sb = new Storyboard();
    DoubleAnimation animation = new DoubleAnimation();
    animation.Duration = TimeSpan.FromSeconds(2);
    animation.AutoReverse = true;
    animation.From = 100;
    animation.To = 400;
    Storyboard.SetTarget(animation, myRec);
    Storyboard.SetTargetProperty(animation,new PropertyPath("Height"));
    sb.Children.Add(animation);
    sb.Begin();
                myRec.Height = 300;

    上边的代码主要是创建一个Double类型的动画,用于修改myRec(一个Rectangle)的Height。关键问题来了,可以看到在sb.Begin()后边手动修改了myRec的Height属性,

    悲剧发生了,你会发现我们这个修改是无效的,之所以造成这个情况是因为动画结束后保持了这个新的属性的值,所以导致了不能再其后修改这个属性的值,不过别担心有解

    决的办法。

    1.修改Animation的FillBehavior为Stop,这样的话就可以保持一个停止的状态,这样在其后修改属性就可以了

    2.给StoryBoard添加Complete事件

        sb.Completed += new EventHandler(sb_Completed);
        void sb_Completed(object sender, EventArgs e)
    {
    Storyboard sb = sender as Storyboard;
    sb.Stop();
    myRec.Height = 300;
    }

    可以看到在Complete事件中调用了StoryBoard的Stop方法将动画停止,然后给属性赋值。

    二、动画的RepeatBehavior属性(重复行为),用于设置动画的重复的效果,可以设置为Forever(不停的重复),可以设置为重复的次数,也可以设置为在一定时间内进行重复

    设置为重复的次数:

    <DoubleAnimation Storyboard.TargetName="cmdGrow" RepeatBehavior="2x"
    Storyboard.TargetProperty="Width" To="300" Duration="0:0:5"></DoubleAnimation>

    这里设置的是 2x,他的语法就是 num*x,意思就是2次。
    后置代码设置方式:

    widthAnimation.RepeatBehavior = new RepeatBehavior(2);

    设置为一定时间内重复:

    <DoubleAnimation Storyboard.TargetName="cmdGrow" RepeatBehavior="0:0:13"
    Storyboard.TargetProperty="Width" To="300" Duration="0:0:5"></DoubleAnimation>

    这里设置为13秒内进行重复。

    后置代码设置方式:

    widthAnimation.RepeatBehavior = new RepeatBehavior(TimeSpan.FromSeconds(13));



    三、FillBehavior属性和AutoReverse属性混合设置

      FillBehavior默认属性为HoldEnd(完成后保持属性的状态),还有一个Stop(完成后保持初始值);

     AutoReverse属性默认值为false,即不会原路返回,可以设置为true进行原路返回。

    FillBehavior    AutoReverse       

    HoldEnd        False                 运行后保持动画后的状态

    Stop             Flase                 运行后立马返回初始状态

    HoldEnd        True                  运行后会按照原路返回,会忽略HoldEnd的保持

    Stop             True                  运行后按照原路返回,和上个效果是一样的

    四、BeginTime(动画开始时间)和SpeedRatio(动画速率)

    BeginTime用来解决多个动画之间的额并发很有效,可以错开多个动画(同一个父级)同时进行。BeginTime可以用来延迟(如果BeginTime为正数)和执行部分(当为负数的时候则在

    Duration-BeginTime时间内执行完毕).

    正的BeginTime值使Timeline的行为延长某个时间。例如,BeginTime为5且Duration为5秒的Timeline整个动画是延迟5秒钟,然后才开始动画的执行。

    这个例子的BeginTime为5,动画Duration为5,则动画会延迟5秒钟开始。

    <DoubleAnimation Duration="0:0:5"  BeginTime="0:0:5" From="100"  To="300" Storyboard.TargetName="myRec" Storyboard.TargetProperty="Width"></DoubleAnimation>

    负的 BeginTime 值使 Timeline(Animation基类) 的行为如同在过去某个时间开始一样。 例如,BeginTime 为 - 2.5 秒且 Duration 为 5 秒的 Timeline 将看起来像是一开始就已完成了一半。

    这个例子中的BeginTime为 -2.5,那么整个动画持续时间只有 2.5秒,并且看起来像是一开始就完成了一半。

    <ColorAnimation Duration="0:0:5" BeginTime="-0:0:2.5" From="Red" To="Green" Storyboard.TargetName="myRec" Storyboard.TargetProperty="(Fill).(Color)"></ColorAnimation>

    时间线的 BeginTime 属性决定时间线的活动期的开始时间。 如果该时间线具有一个父时间线,则 BeginTime 属性决定在其父时间线(ParallelTimeline此类在WPF中提供在Silverlight原生dll中并未发现,定义可以包含子 Timeline 对象的时间段。 这些子时间线将按各自的 BeginTime 属性变为活动状态。 此外,子时间线也可相互重叠(并行运行)。)启动后,该时间线需要多长时间才能启动。

    这个例子中ParallelTimeline的BeginTime为5秒,动画的Begin为5秒,那么整个动画将会延迟10秒

    <ParallelTimeline BeginTime="0:0:5">
    <DoubleAnimation Storyboard.TargetName="DelayedAnimationWithDelayedParentRectangle"Storyboard.TargetProperty="Width"BeginTime="0:0:5"From="100"To="600"Duration="0:0:5"/>
    </ParallelTimeline>


    SpeedRatio支持动画加速执行,但是这个SpeedRatio不会影响BeginTime,因为动画还是在BeginTime之后执行的。

    虽然速率是2,但是整个动画还是在BeginTime5秒之后执行的,因为这个速率仅仅对动画有效,仅仅是BeginTime之后动画的速率。

    <DoubleAnimation Duration="0:0:5"  SpeedRatio="2"  BeginTime="0:0:5" From="100"  To="300" Storyboard.TargetName="myRec" Storyboard.TargetProperty="Width"></DoubleAnimation>

    五、StoryBoard对象

    StoryBoard不再过多介绍是干嘛,在此主要介绍其的一些方法

    Begin开始动画, Pause (Storyboard)停止动画, Resume继续播放StoryBoard的动画, Seek将StoryBoard移动到指定的时间点,Stop (Storyboard)停止动画.

    以上的方法除了Seek之外,其他方法均为直接使用StoryBoard对象调用,看下Seek的调用方法。

      sb.Seek(TimeSpan.FromSeconds(3));

    这种方式直接将动画定位到3秒的位置。

    fadeStoryboard.Seek(
    TimeSpan.FromSeconds(fadeAnimation.Duration.TimeSpan.TotalSeconds/2));

    将动画指定到中间的位置(其中的fadeAnimation为Animation)。

    六、Duration,这个属性竟然也有用错的时候,该属性就是表示一个动画执行过程的时间,格式就是 0:0:0这样的格式,本人在实例过程中由于偷懒仅仅写了一个10,导致动画怎么着也不会执行,最后才发现是Duration的格式错误引起的。

    七、关键帧动画(之前说的几乎都是插值动画的用法,下面介绍复杂的动画关键帧动画,关键帧动画是可以实现更为真实的动画,包括加速度和减速度),线性插值动画是在两个属性值之间进行你给渐变,而一个关键帧动画是可以在任意多个的目标属性值之间进行渐变(这里的意思是线性插值动画通过指定From和To以及By属性让动画在一定的时间内完成动画的,而关键帧动画是通过Value让动画在某一个时间点达到某一个属性的一个值)

    关键帧动画元素的名称就是在线性动画的名称后面加上UsingkeyFrames,分别为:

         DoubleAnimationUsingkeyFrames(Doubel关键帧动画)

         ColorAnimationUsingKeyFrames(Color关键帧动画)

         PointAnimationUsingKeyFrames(Point关键帧动画)

    以上三种关键帧动画都支持三种不同的关键帧补间类型,分别为Linear(线性),Discrete(离散),Splined(多键),三种格式的作用见下表.

    名称

    格式

    描述

    Linear

    Linear 类型 KeyFrame

    可以使目标属性的值在持续时间内产生固定频率的渐变,其属性值会时时的被反映出来

    Discrete

    Discrete 类型 KeyFrame

    可以使目标属性的值从一个值直接跳到下一个值,这个过程不产生渐变效果,只会显示一个结果.

    Splined

    Splined 类型 KeyFrame

    可以使目标属性值产生精确的渐变,通过keySpline属性可以模拟更真实的动画

    关键帧动画包含两个重要的属性KeyTime属性和Value属性,作用是在KeyTime属性指定的某个时间点对目标的Value进行控制,KeyTime就是指定在何时达到这个关键帧的Value,切记这里的KeyTime表示的不是这个动画持续多长时间,而是在这个时间点显示的效果是Value,这点和线性插值动画动画中的Duration是不同的(Duration表示这个动画持续多长时间),当然这也是因为线性插值动画在一个动画中是不能有多个动画的,所以其Duration的本质应和KeyTime一致,由于在关键帧中一个动画可以包含多个效果,所以就产生了某一时刻对应的动画.

            <Storyboard x:Name="myStory1">
    <!—Linear方式 -->
    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="myEllipse1"
    Storyboard.TargetProperty
    =" (UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.X)">
    <LinearDoubleKeyFrame Value="500" KeyTime="00:00:02"></LinearDoubleKeyFrame>
    </DoubleAnimationUsingKeyFrames>
    </Storyboard>
            <Storyboard x:Name="myStory2">
    <!—Discrete方式 -->
    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="myEllipse2"  Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.X)">
                    <DiscreteDoubleKeyFrame Value="500" KeyTime="00:00:2.5"></DiscreteDoubleKeyFrame>
    </DoubleAnimationUsingKeyFrames>
    </Storyboard>

    这个是难点,这里的Spline比上两个多了一个属性就是KeySpline(获取或设置定义此关键帧的动画进度的两个控制点,两个控制点,用来指定定义关键帧进度的三次方贝塞尔曲线。在描述关键样条时,贝塞尔曲线的起点始终为 0,终点始终为 1,这也就是只定义两个控制点的原因。 所生成的曲线指定如何在一个时间段内内插动画;也就是说,该曲线表示该时间段内动画的目标属性的变化速率。)

     <Storyboard x:Name="myStory3">
                    <!Splin方式 -->
    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="myEllipse3" BeginTime="00:00:00"
    Storyboard.TargetProperty
    ="(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.X)">
    <SplineDoubleKeyFrame KeyTime="00:00:4.5" KeySpline="0,0 1,0" Value="500"></SplineDoubleKeyFrame>
    </DoubleAnimationUsingKeyFrames>
    </Storyboard>
    使用了多个LinearColorKeyFrame进行颜色的渐变

    <Storyboard>
    <!--使用ColorAnimationUsingKeyFrames-->
    <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="myEllipse"
    Storyboard.TargetProperty
    ="(Ellipse.Fill).(SolidColorBrush.Color)">
    <LinearColorKeyFrame Value="Yellow" KeyTime="00:00:1"></LinearColorKeyFrame>
    <LinearColorKeyFrame Value="Red" KeyTime="00:00:2"></LinearColorKeyFrame>
    <LinearColorKeyFrame Value="Green" KeyTime="00:00:4"></LinearColorKeyFrame>
    </ColorAnimationUsingKeyFrames>
    </Storyboard

    使用了多个LinearPointKeyFrame  进行坐标的变化

    <Storyboard>
    <PointAnimationUsingKeyFrames Storyboard.TargetName="myEllipse1" Storyboard.TargetProperty="Center" AutoReverse="True">
    <LinearPointKeyFrame Value="50,50" KeyTime="0:0:0"></LinearPointKeyFrame>
    <LinearPointKeyFrame Value="250,230" KeyTime="0:0:2"></LinearPointKeyFrame>
    <LinearPointKeyFrame Value="450,50" KeyTime="0:0:4"></LinearPointKeyFrame>
    <LinearPointKeyFrame Value="650,230" KeyTime="0:0:6"></LinearPointKeyFrame>
    <LinearPointKeyFrame Value="900,50" KeyTime="0:0:8"></LinearPointKeyFrame>
    </PointAnimationUsingKeyFrames>
    </Storyboard>


    除了上述的三种关键帧动画支持的类型之外还有一种EasingPointKeyFrame(EasingDoubleKeyFrame,EasingColorKeyFrame),就是他,是不是很熟悉呢

    没错就是使用了Ease效果的关键帧动画,看个用法。

      <DoubleAnimationUsingKeyFrames>
    <EasingDoubleKeyFrame KeyTime="0:0:3" Value="12">
    <EasingDoubleKeyFrame.EasingFunction>
    <BackEase></BackEase>
    </EasingDoubleKeyFrame.EasingFunction>
    </EasingDoubleKeyFrame>
    </DoubleAnimationUsingKeyFrames>

    他们是不能单独使用的,需要配合DoubleAnimationUsingKeyFrames或者ColorAnimationUsingKeyFrames或者PointAnimationUsingKeyFrames来使用,可以指定KeyTime以及Value和最重要的EasingFunction,EasingFunction用法和Ease的用法一样,详情可参见本博客其他文章.



  • 相关阅读:
    Tomcat启动startup.bat闪退和JRE_HOME错误
    页面布局:一侧固定宽度,一侧自适应
    iOS-数据持久化-CoreData
    iOS-数据持久化-SQlite3
    iOS-数据持久化-偏好设置
    iOS-数据持久化-对象归档
    iOS-数据持久化-属性列表
    iOS-数据持久化基础-沙盒机制
    iOS-数据持久化详细介绍
    iOS-网络处理框架AFN
  • 原文地址:https://www.cnblogs.com/ListenFly/p/2218331.html
Copyright © 2020-2023  润新知