Silverlight 动画沿着任意数学路径通过缓动






4.90/5 (13投票s)
描述了一个沿任意路径动画对象移动的简单算法
引言
大约两年前,一篇非常有趣的关于如何在 Silverlight 中创建沿任意路径进行动画的文章被发表 Silverlight 中的路径动画。它还提供了 DoubleAnimationUsingPath
和 PointAnimationUsingPath
类,这些类与相应的 WPF 类相似(与 WPF 不同,Silverlight 默认没有此功能)。
然而,上述文章中用于创建动画的算法相当复杂,涉及通过一系列线段连接来近似路径曲线(展平)。
这里提出的算法要简单得多,但却能取得相同的结果,它使用了 Silverlight 内置的缓动功能。我的目的不是创建模仿 WPF 功能的 DoubleAnimationUsingPath
和 PointAnimationUsingPath
类——尽管使用这种方法可以创建它们——而是展示如何创建沿任何数学定义的路径(例如曲线、一系列连接的曲线或一系列连接的线段)的动画。
在此基础上,本文还展示了如何创建点沿任意路径运动的视觉效果。
背景
演示
让我们从头开始。以下是基于本文代码的 Silverlight 演示: 路径动画演示。
以下是演示截图
一点点数学知识
路径的数学定义之一是,在 X
、Y
向量平面上的路径是满足以下方程的点集:x = X(t)
和 y = Y(t)
,其中 X
和 Y
是函数(对于连接的路径,它们必须是连续的,对于平滑的路径,它们应该具有连续的导数)。在上述方程中,“t
”是一个实数参数。有时,“t
”可以定义为与路径上当前点到路径原点的距离成比例:在这种情况下,路径是均匀的,因为介于 t1
和 t2
之间的路径长度仅取决于 (t2-t1)
。然而,有时均匀路径参数化不是最方便的,在本文中我给出了稍微非均匀参数化的示例。
上述定义,再加上我们可以使用缓动函数来动画化 Silverlight 对象(例如平移变换)的 X 和 Y 坐标的事实,使我们能够轻松地创建沿任意数学路径的 Silverlight 动画,而无需诉诸于昂贵的近似等技术。
数学路径示例
最简单的路径是线性路径,由以下方程组描述
x = xFactor * t + xOffset;
y = yFactor * t + yOffset;
以下是描述圆形路径的路径方程
x = cos(2pt) * scalingFactor
y = sin(2pt) * scalingFactor
在这种情况下,“t
”是角度。要使其成为椭圆路径,只需为“x
”和“y
”坐标设置不同的缩放因子,但那样的话参数化的均匀性就会被打破。
再一点数学知识(缓动数学)
现在,让我们用数学方程来表达带缓动函数的动画。我实际上是通过实验来弄清楚的(因为我在网上找不到)。以下公式描述了缓动动画在时间中的行为
v = (V2 - V1)/T * f(t/T) + V1
其中“v
”是最终动画值,“t
”是时间参数,“T
”是相关的时间周期(对于带帧的动画,是帧之间的时间;对于 DoubleAnimation
,是“To
”和“From
”值之间的时间),V2
和 V1
分别是动画结束和开始时的动画值,且没有缓动,而“f
”是缓动函数。在上面的公式中,我们假设是线性动画(非样条曲线)和默认的 EasingMode
。
在我们的代码中,我们总是设置 (DoubleAnimation
的 From
和 To
属性) V1 = 0
, V2 = 1
。我们还处理归一化时间,因此假设 T = 1
。因此,我们可以写成
v = f(t)
其中“t
”是归一化时间,f(t)
是 Easing
函数。
使用代码
本文介绍了三个 Silverlight 演示,说明了上述概念。
单点路径动画演示
此演示展示了如何创建沿任意数学路径的单个对象动画,并以椭圆和贝塞尔曲线动画为例。该演示出现在“Single Point Path Animation Demo”标题下,相应的代码位于 SinglePointPathAnimation
VS 2010 解决方案中。
该解决方案代码还介绍了一些便于创建此类动画的通用类:GenericEasingFunction
、OneDAnimation
和 TwoDAnimation
。
GenericEasingFunction
是 IEasingFunction
接口的一个简单实现,它公开了 EasingFunc
属性,允许将 Easing
函数设置为委托/lambda 表达式。
OneDAnimation
类提供了一种在 DoubleAnimation
上设置 Easing
函数的方法。
TwoDAnimation
由两个 OneDAnimation
对象组成,分别对应 TranslateTransform
的“X
”和“Y
”坐标动画。
以下是如何使用代码沿椭圆路径创建动画
// animation along an elliptic path
TwoDAnimation animation1 =
new TwoDAnimation
{
TheTranslateTransform = TheTranslateTransform1,
XFunction = (t) => Math.Cos(t * (2.0 * Math.PI)) * 50,
YFunction = (t) => Math.Sin(t * (2.0 * Math.PI)) * 50 * 1.5
};
animation1.XAnimation.From = 0;
animation1.XAnimation.To = 1;
animation1.YAnimation.From = 0;
animation1.YAnimation.To = 1;
Storyboard sb1 = new Storyboard();
sb1.Duration = TimeSpan.FromSeconds(4);
animation1.SetStoryboard(sb1);
sb1.RepeatBehavior = RepeatBehavior.Forever;
sb1.Begin();
请参见 MainPage.xaml.cs 文件。
沿贝塞尔曲线路径的动画以相同的方式创建,只是 XFunction
和 YFunction
lambda 表达式不同。
沿任意路径的多点动画
我们希望创建一种动画效果,其中多个对象沿任意路径分散(最好是均匀分布),并且动画使这些对象沿同一方向沿路径移动,如上面 Silverlight 演示所示。这是通过创建沿路径移动的对象来实现的,这些对象相对于路径上的前一个对象,沿着“t
”参数偏移 Delta。对象将沿 Delta 移动,然后从其原点重复移动。这将创建多个对象一直沿路径移动到末尾的错觉。
多点动画的演示出现在“Multiple Point Animation Demo”标题下。相应的 VS 2010 解决方案名为 MultiplePointsPathAnimation
。
在此解决方案下开发了更多通用代码,如下所述。
我们显然需要一个能够生成相同类型对象的工厂(因为我们需要在路径上放置多个对象)。ElementFactory
是这样一个工厂的一个非常简单的示例,它创建红点。它还将创建的元素添加到它们的父面板中。
路径上的这些不同对象将明显具有不同的动画函数。这些动画函数将通过对定义整个路径移动的动画函数进行偏移来生成。为了创建这些函数,我们使用 FuncWithShift
类。它的构造函数接收原始函数和偏移值,其 ShiftedFunc
属性返回偏移后的函数。
有一个 ShiftFuncFactory
类使用 FuncWithShift
来生成函数的多个偏移。它有一个 CurrentShift
属性,可以更改以操纵偏移值,而其 ShiftedFunc
属性返回结果的偏移函数。ShiftFuncFactory
类假定偏移函数仅在时间参数从 0
变为 Delta 时才起作用(这是为了说明对象应该只移动到动画开始时下一个对象所在的位置,而不应该移动到路径的末尾)。ShiftFuncFactory
类还有一个 ExternalShift
属性,允许偏移整个路径(我在“Running Letters”演示中使用它来相对移动字母)。
最后,ItemsAlongPathFactory
类实际上在其 SetStoryboar
函数中构建动画。它使用其 XFunc
和 YFunc
属性来设置路径函数,并使用 ShiftFuncFactory
功能来构建相应的函数偏移。
以下是如何在 MainPage.xaml.cs 文件中创建多点椭圆动画
// Elliptic path
Func<double, /> xFunc1 =
t => Math.Cos(t * (2.0 * Math.PI)) * 50;
Func<double, /> yFunc1 =
t => Math.Sin(t * (2.0 * Math.PI)) * 50 * 1.5;
ItemsAlongPathFactory itemsFactory1 =
new ItemsAlongPathFactory
{
TheElementFactory =
new ElementFactory
{
ThePanelToAddElementTo = Grid1
},
DeltaShift = 0.1,
XFunc = xFunc1,
YFunc = yFunc1
};
Storyboard sb1 = new Storyboard();
sb1.Duration = TimeSpan.FromSeconds(0.1);
itemsFactory1.SetStoryboard(sb1);
//sb.AutoReverse = true;
sb1.RepeatBehavior = RepeatBehavior.Forever;
sb1.Begin();
使用不同的路径函数以相同的方式创建贝塞尔曲线路径的多点动画。
Running Letters 演示
我使用了上述代码和概念来创建“Running Letters”演示。该演示只是让红点沿“AWebPros
”字母指定的路径运行。相应的代码位于“RunningLetters
”VS 2010 项目中。
关注点
本文描述了一种使用 Easing
函数在任意数学路径上创建 Silverlight 动画的新、更简单的方法。此外,本文将这种新方法应用于创建任意路径上的多对象动画。
历史
- 2011 年 2 月 1 日:初始发布