原文:《Programming WPF》翻译 第8章 4.关键帧动画

到目前为止,我们只看到简单的点到点的动画。我们使用了To和From属性或者By属性来设计动画——相对于当前的属性值。这很适合简单的动画,但是我们可以构造序列来创建更复杂的动画,这可能是非常麻烦的。幸运的是,这是没有必要的。WPF提供了动画对象,允许我们详细指出一系列时间和值。

在影视中传统的动画中,这是普通的开始——通过绘制最重要的动画步骤。这些关键帧定义了场景的基本流程,捕获了它的最重要的点。只要一旦这些关键帧是满意的,是保留的帧绘图。这些关键帧之间的图像并不要求非常创造性的输入,它们只是简单的打算添加进去,从一个关键帧到另一个。WPF优化了同样的概念。你可以考虑简单的From和To方法——等价于提供两个关键帧,一个“before”帧和一个“after”帧——WPF会为你添加这两个帧。关键帧动画简单的扩展了多个帧的概念。

作为最简单的动画类型,关键帧仍然一次性为属性设定目标。因此它们并不与传统动画中关键帧一样,每一帧组成了整个的绘图。你不能提供两个绘图并告诉WPF从一个变换到另一个。

关键帧动画类型使用了命名装换TypeAnimationUsingKeyFrames。示例8-24显示了一个简单的动画:一个弹起的矩形,使用到了DoubleAnimationUsingKeyFrames。

示例8-24

<Window Text="Key Frames" Width="850" Height="300"

    xmlns="http://schemas.microsoft.com/winfx/avalon/2005"

    xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005">





    <Window.Storyboards>

        <SetterTimeline TargetName="rect" Path="(Canvas.Left)"

                        RepeatBehavior="Forever" AutoReverse="True">

            <DoubleAnimation From="0" To="800" Duration="0:0:10" />

        </SetterTimeline>



        <SetterTimeline TargetName="rect" Path="(Canvas.Top)">

            <DoubleAnimationUsingKeyFrames Duration="0:0:2"

                                           RepeatBehavior="Forever">

                <DoubleAnimationUsingKeyFrames.KeyFrames>

                    <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0" />

                    <LinearDoubleKeyFrame Value="50" KeyTime="0:0:0.5" />

                    <LinearDoubleKeyFrame Value="200" KeyTime="0:0:1" />

                    <LinearDoubleKeyFrame Value="50" KeyTime="0:0:1.5" />

                    <LinearDoubleKeyFrame Value="0" KeyTime="0:0:2" />

                </DoubleAnimationUsingKeyFrames.KeyFrames>

            </DoubleAnimationUsingKeyFrames>

        </SetterTimeline>

    </Window.Storyboards>



    <Canvas>

        <Rectangle x:Name="rect" Fill="Red" Width="20" Height="20" />

    </Canvas>

</Window>

这里有两个timeline。第一个移动矩形从左到右,使用常规的DoubleAnimation,第二个通过使用DoubleAnimationUsingKeyFrames控制了垂直的位置。这控制了5个帧,详细指出了矩形的需要的垂直位置,在半秒的时间内。如图8-12所示,这些关键帧显示了这个矩形,在它的跳动的顶部和底部,伴随着中途的点比中间点稍微高一点,指出一段时间的速度渐变。WPF为我们在这些位置之间加入了新元素。

8-12



示例8-24中每个关键帧的值都使用LinearDoubleKeyFrame详细指出。这说明了使用了线形添写。改变的速度是介于两个帧之间的常量。这就引起了运动并不是特别平滑的。这个矩形在它下降时提高速度,而速度上的改变发生在可见的“阶段”——从动画的一幕到下一幕。我们可以减少这种影响,通过添加更多的关键帧,但是这里有一条更容易的方式。不是图8-13中左边显示的简单线性插值,而是获取一个曲线插值如右边显示,提高了平滑度,而不需要添加更多的关键帧。

8-13



为了在我们想要的动画速度上获取更平滑的改动,我们可以使用SplineDoubleKeyFrame。带有一个样条关键帧,一条贝塞尔曲线详细指出了动画值是应该如何改变的。可是,这种曲线使用的方式并不是完全直接的。正如我们在第7章看到的,贝塞尔曲线可以用于定义曲线形状。可是,使用动画,我们不能简单地定义路径。一个点沿示例中的贝塞尔曲线而行。这条曲线是一个二维的形状,但是这个动画对象仅修改了y轴,这意味着它只在一个维度上产生影响。(记得示例8-24使用了2个SetterTimeline元素,每个都对应一个维度。)

代替以定义点的路径,贝塞尔曲线在一个样条关键帧上定义了一个数学函数的形式。这个函数把它的输入理解为关键帧的流逝时间的比例。作为输出,它提供了一个数字,指出之前的和当前的值混合在一起的比例。这条曲线总是从(0,0)移动到(1,1),但是你定位这两个控制点,决定了它的形状在这些极限之间。使用关键帧的KeySpline属性设置这些值。

图8-14显示了3个动画样条的示例,控制点标记在小矩形上。记得这些曲线简单的决定了动画前进的速度。第一个“曲线”是一条直线,意味着这个动画以常速前进。这等价于一个LinearDoubleKeyFrame。第二条曲线指出了动画开始缓慢而后加速。第三条曲线显示了动画开始迅速而后减速到停止。

图8-14



示例8-25是示例8-24的对关键帧的修改版本。这个动画传递了同样的关键帧值,但是使用样条来指出动画的速度应该逐渐改变。这使得这个动画感觉很平滑,而不需要添加更多的关键帧。

示例8-25

<SetterTimeline TargetName="rect" Path="(Canvas.Top)">

    <DoubleAnimationUsingKeyFrames Duration="0:0:2" RepeatBehavior="Forever">

        <DoubleAnimationUsingKeyFrames.KeyFrames>

            <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0" />

            <SplineDoubleKeyFrame Value="50" KeyTime="0:0:0.5"

                                  KeySpline="0.4,0 0.75,0.75" />

            <SplineDoubleKeyFrame Value="200" KeyTime="0:0:1"

                                  KeySpline="0.2,0.2 1,0.4" />

            <SplineDoubleKeyFrame Value="50" KeyTime="0:0:1.5"

                                  KeySpline="0,0.3 0.75,0.75" />

            <SplineDoubleKeyFrame Value="0" KeyTime="0:0:2"

                                  KeySpline="0.25,0.25 0.6,1" />

        </DoubleAnimationUsingKeyFrames 

.KeyFrames>

    </DoubleAnimationUsingKeyFrames>

</SetterTimeline>

第一帧仍然使用LinearDoubleKeyFrame,因为这里没有“before”帧以进行插值。两个“downward”关键帧使用了曲线形状——类似于图8-14中间的那个。这导致了这个动画开始缓慢然后加速,正如你希望的在一个下落对象的动画中。两个“upward”关键帧使用了曲线形状——类似于图8-14右边的那个。这导致了这个动画逐渐缓慢直到这个对象到达顶部。这就提供了一个更有力的可视化近似:关于一个真实的对象是如何运动的。

这里还有一种可利用的的插值样式:四点插值细分算法。如果你使用了这样一个关键帧,WPF根本不会真正地“插值”。它会突然跳到详细指定的值。这就易于引进中断到你的动画中,如果必要。

注意到,WPF提供了关键帧的版本——大多数动画类型都支持它,不仅是Double类型,表8-2列出了这些类型。

Table 8-2. Key-frame animation types

BooleanAnimationUsingKeyFrames

PointAnimationUsingKeyFrames

ByteAnimationUsingKeyFrames

Rect3DAnimationUsingKeyFrames

CharAnimationUsingKeyFrames

RectAnimationUsingKeyFrames

ColorAnimationUsingKeyFrames

Rotation3DAnimationUsingKeyFrames

DecimalAnimationUsingKeyFrames

SingleAnimationUsingKeyFrames

DoubleAnimationUsingKeyFrames

Size3DAnimationUsingKeyFrames

Int16AnimationUsingKeyFrames

SizeAnimationUsingKeyFrames

Int32AnimationUsingKeyFrames

StringAnimationUsingKeyFrames

Int64AnimationUsingKeyFrames

ThicknessAnimationUsingKeyFrames

MatrixAnimationUsingKeyFrames

Vector3DAnimationUsingKeyFrames

Point3DAnimationUsingKeyFrames

VectorAnimationUsingKeyFrames

《Programming WPF》翻译 第8章 4.关键帧动画的更多相关文章

  1. 《Programming WPF》翻译 第8章 5.创建动画过程

    原文:<Programming WPF>翻译 第8章 5.创建动画过程 所有在这章使用xaml举例说明的技术,都可以在代码中使用,正如你希望的.可是,代码可以使用动画在某种程度上不可能在x ...

  2. 《Programming WPF》翻译 第9章 5.默认可视化

    原文:<Programming WPF>翻译 第9章 5.默认可视化 虽然为控件提供一个自定义外观的能力是有用的,开发者应该能够使用一个控件而不用必须提供自定义可视化.这个控件应该正好工作 ...

  3. 《Programming WPF》翻译 第9章 6.我们进行到哪里了?

    原文:<Programming WPF>翻译 第9章 6.我们进行到哪里了? 只有当任何内嵌控件都没有提供你需要的底层行为时,你将要写一个自定义控件.当你写一个自定义控件,你将要使用到依赖 ...

  4. 《Programming WPF》翻译 第9章 4.模板

    原文:<Programming WPF>翻译 第9章 4.模板 对一个自定义元素最后的设计考虑是,它是如何连接其可视化的.如果一个元素直接从FrameworkElement中派生,这将会适 ...

  5. 《Programming WPF》翻译 第9章 3.自定义功能

    原文:<Programming WPF>翻译 第9章 3.自定义功能 一旦你挑选好一个基类,你将要为你的控件设计一个API.大部分WPF元素提供属性暴露了多数功能,事件,命令,因为他们从框 ...

  6. 《Programming WPF》翻译 第9章 2.选择一个基类

    原文:<Programming WPF>翻译 第9章 2.选择一个基类 WPF提供了很多类,当创建一个自定义元素时,你可以从这些类中派生.图9-1显示了一组可能作为类--可能是合适的基类, ...

  7. 《Programming WPF》翻译 第9章 1.自定义控件基础

    原文:<Programming WPF>翻译 第9章 1.自定义控件基础 在写一个自定义控件之前,你需要问的第一个问题是,我真的需要一个自定义控件吗?一个写自定义控件的主要原因是为了用户界 ...

  8. 《Programming WPF》翻译 第8章 6.我们进行到哪里了?

    原文:<Programming WPF>翻译 第8章 6.我们进行到哪里了? 动画可以增强应用程序的交互感.它有利于更平滑的转换--当条目出现或消失的时候.它应该,当然,被用于体验和重新着 ...

  9. 《Programming WPF》翻译 第8章 3.Storyboard

    原文:<Programming WPF>翻译 第8章 3.Storyboard Storyboard是动画的集合.如果你使用了标记,所有的动画必须要被定义在一个Storyboard中.(在 ...

随机推荐

  1. Java Timer 定时器的使用

    设置定时任务很简单,用Timer类就搞定了. 一.延时执行首先,我们定义一个类,给它取个名字叫TimeTask,我们的定时任务,就在这个类的main函数里执行. 代码如下:package test;i ...

  2. C++ 中 struct和class 的区别

    来自:http://hi.baidu.com/pengxiangbobin19890125/blog/item/b05586eee77300212df53411.html   C++ prime  中 ...

  3. window.open和window.close的使用详解

    有时候,我们想通过JS实现一个<a>的新开标签的效果,此时我们想到了window.open方法实现.那么window.open到底应该怎么使用呢?   我们知道window.open可以新 ...

  4. [置顶] API相关工作过往的总结之Sandcastle简要使用介绍

    Sandcastle介绍 在微软推出Sandcastle之前,人们倾向于选择开源的NDoc(.NET代码文档生成器).NDo可以将 C#.NET 编译生成的程序集和对应的 /doc XML文档,自动转 ...

  5. Spring的工作原理核心组件和应用

    Spring框架 Spring 是管理多个java类的容器框架,注意是类不管理接口. Spring 的主要功能 Ioc 反转控制和 DI 依赖注入. 注入的方式可以是构造函数赋值也可以是 set方法赋 ...

  6. 前端开发利器—FIDDLER 转

    http://www.cnblogs.com/yuzhongwusan/archive/2012/07/20/2601306.html 前端开发利器—FIDDLER 1.Fiddler相对其他调试工具 ...

  7. (转)iOS Wow体验 - 第三章 - 用户体验的差异化策略

    本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第三章译文精选,其余章节将陆续放出.上一篇:Wow ...

  8. hdu 4666 Hyperspace

    曼哈顿距离,两个点设为(x1,y1),(x2,y2),其距离为|x1-x2|+|y1-y2| #include <cstdio> #include <set> #include ...

  9. VMware vSphere 5.5的12个更新亮点(1)

    [IT专家网虚拟化]在VMworld 2013大会上发布的VMware vSphere 5.5版本提供的增强和改进,横跨从hypervisor到管理整个堆栈,提升了VMware的性能.可伸缩性和可用性 ...

  10. linux高级技巧:heartbeat+lvs(一)

    1.heartbeat一个简短的引论:        Heartbeat 项目是 Linux-HA project的一个组成部分,它实现了一个高可用集群系统.心跳服务和集群通信是高可用集群的两个关键组 ...