在代码中组合 Silverlight 动画
本文介绍如何通过组合动画和缓动函数来生成类似于 Google 的 Les Paul(吉他) Doodle 以及国家地理频道“测试你的大脑”节目等特效。
引言
尽管 Silverlight 中的 Storyboard 动画技术非常丰富,但仍存在一些不足。本文将介绍如何通过巧妙地组合/扭曲/破解它们来克服这些不足。最终,Silverlight 可以轻松生成类似于 Google 于 2011 年 10 月发布的 Google Doodle 和国家地理频道 “测试你的大脑”节目 的动画效果。大多数动画是通过代码实现的。
背景
读者应基本熟悉 Silverlight 中的 Storyboard、PlaneProjection 以及其他基本概念。
使用代码
应用程序包含一个主页,其中包含一个分割控件,将页面水平分成两部分。上半部分包含几个按钮,点击这些按钮将用户带到一个演示所述动画的页面。
代码使用 C# 和 Visual Studio 2010 旗舰版开发。
让我们从 Canvas 动画页面开始。
Canvas 动画页面
此页面演示了如何在 Canvas 中移动一个球体(在本例中为椭圆),使其在 Canvas 的边缘反弹。一种移动椭圆的方法是改变其 margin 属性。不幸的是,Silverlight 没有 thickness 动画类。虽然 Storyboard 具有 auto reverse 属性,但要实现弹跳球体的随机永久运动可能会非常困难。
为了实现这一点,我采用了一个定时器函数来完成工作。该页面的逻辑是,每次调用定时器函数时,都会根据球体相对于 Canvas 边界的位置,更新当前的 thickness(基于 dxCircle
和 dyCircle
)。在撞击边界后,会改变 dxCircle
和/或 dyCircle
的符号,以模拟反弹。同时,会移动 LayoutRoot
的 opacity mask 的 radial brush 的原点,以产生反弹辉光效果。
此页面还包含两种可以轻松实现的自由手绘。代码本身很直观。
弹跳动画页面
此页面模拟了一个三维弹跳球体。点击 Canvas,一个球体将凭空出现并向观看者弹跳。
任何弹跳都包含两个部分:垂直运动,在本例中是从 Y 轴上的一个点落下;以及水平运动,在本例中是向观看者移动(在 Z 轴上)。Z 轴运动是通过移动椭圆(PlaneProjection)的 LocalOffsetZ
向前(从 0 到 750)来实现的。Y 轴运动是通过改变椭圆的 margin 的 top 来实现的。与之前一样,由于 Silverlight 没有 thickness 动画类,因此通过 slider 来改变椭圆的 margin,如下所示。
private void sliderY_ValueChanged(object s, RoutedPropertyChangedEventArgs<double> e)
{
Thickness thick = myEllipse.Margin;
thick.Top = (double)sliderY.Value;
myEllipse.Margin = thick;
}</double>
现在,如果我将 slider 的 value 属性在 Minimum
和 Maximum
值之间进行动画处理,它将最终动画化椭圆的 margin 属性,从而实现弹跳效果。等等,我们还没有完成,弹跳模拟仍然需要处理。
水平和垂直运动都捕获在各自 slider 的 ValueProperty
中。对应于椭圆水平运动的 slider 的 DoubleAnimation
对象附加到 CircleEase
,而对应于椭圆垂直运动的 slider 的 DoubleAnimation
对象附加到 BounceEase
。就是这样,这就完成了。让我解释一下。
当水平运动仍在进行时,BounceEase
会介入,将 slider 的值推到最大,然后短暂拉回,再次推到最大,从而模拟弹跳球体的效果。仔细观察 sliders,可以看到弹跳动画正在进行。
将 BounceEase
的 Easingmode
属性设置为 EaseOut
可以模拟重力,球体在接近地面时加速,在接近下一个顶点时逐渐减速,并继续此过程直到静止。
还有一些其他的设置可以为动画增添生机:
- 阴影同时收窄自身与椭圆之间的间隙(阴影深度属性随着动画的进行而缩小)。
- 阴影的模糊值也同时减小(模糊半径属性随着动画的进行而减小)。
- 径向渐变刷(Radial brush)同时将其原点(Origin)和中心(Center)从 Point (0.5, 0) 移动到 Point (.5, 1) 数次(再次通过 slider),模拟球体的滚动。
弧形动画页面
此页面模拟了一个振动的弦、一个时钟的摆锤和一个正在运球的球。振动的弦与 Google 在 2010 年 Les Paul 96 岁生日时展示的 Google Doodle 非常相似。在这里,我将使用 Microsoft Silverlight 来演示。
振动的弦
弧形(Arc)有一个起点、终点和大小属性。大小决定了弧形的绘制高度。通过动画处理大小属性的高度足以模拟振动的弦。与之前一样,我将一个 slider 附加到此属性并动画化 slider,因为没有大小动画类。为了实现振动弦的来回运动,我执行以下操作:
- 将 Storyboard 的 double animation 对象的
AutoReverse
属性设置为 true。 - 获取 Storyboard 的 completed 事件处理程序。
在 completed 事件处理程序中,首先停止 Storyboard,然后找出预设计数器(nCounterArc2
、nCounterArc1
、nCounterArc3
)是奇数还是偶数,并相应地更改弧形的 SweepDirection
。在此之后,我递增计数器(nCounterArc2
、nCounterArc1
、nCounterArc3
)变量,并将 slider 的 Maximum
值减少 5,以模拟振动弦的衰减。这会一直进行,直到 slider 的 Maximum
值达到零,此时动画完全停止;否则,将使用新值重新启动动画。代码如下所示。
private void DoubleAnimation_Completed_XAML_Arc2(object sender, EventArgs e)
{
nCounterArc2++;
StBoardXAMLArc2.Stop();
if ((nCounterArc2 % 2) == 0)
myArc2.SweepDirection = SweepDirection.Clockwise;
else
myArc2.SweepDirection = SweepDirection.Counterclockwise;
if (sliderHeightArc2.Maximum <= 5)
sliderHeightArc2.Maximum--;
else
sliderHeightArc2.Maximum -= 5;
if (sliderHeightArc2.Maximum <= 0)
{
StBoardXAMLArc2.Stop();
return;
}
StBoardXAMLArc2.Begin();
}
摆锤动画代码与振动弦动画代码非常相似。
运球的球
这仅仅是一个光学错觉,如国家地理频道 “测试你的大脑”节目 所演示的那样。这个错觉有以下步骤(如果你仔细观察,只有阴影在运球,球本身并没有运球):
- 椭圆用径向渐变刷(Radial brush)进行皮肤化处理。径向渐变刷将其
Origin
和Center
从 Point (0.5, 0) 移动到 Point (.5, 1) 数次(再次通过 slider),模拟球体的滚动。 - 椭圆的投影指向一个
PlaneProjection
对象。通过改变其LocalOffsetYProperty
从 -100 到 1000 来移动椭圆。 - 运球效果是通过振荡其
Dropshadow
对象的ShadowDepth
和BlurRadius
来实现的。这也通过一个 slider 来完成。
圆形动画页面
此页面展示了如何将圆组合在一起并一起进行动画处理。在构造函数中,使用随机填充的 Radialgradient
刷创建了一组椭圆。每个椭圆都被赋予绕其 Z 轴的旋转,其 CenterofRotationX
移动到 3 个单位。这以圆形方式显示了所有椭圆。页面中的每个 slider 负责一个属性,例如宽度、高度、CenterofRotationX
、Z 轴旋转(RotationZ
),这些属性在同一个 Storyboard 中一起进行动画处理,从而产生效果。
注意:我保留了 sliders 的可见性,以便开发人员能够清晰地理解动画;当然,在生产环境中,它们将被隐藏。有几行注释掉的代码,你可以打开注释来模拟其他对称动画。