Expression Blend & Silverlight 中的忙碌的、令人眼花缭乱的 Bee-sley 螺旋动画






4.89/5 (45投票s)
使用螺旋线形状、PathListBoxes、Storyboards 和 Behaviours,在不写代码的情况下模拟随机运动动画
引言
欢迎来到我的 **Expression Blend** & **Silverlight** 的 **第 8 个初学者** 教程。这次纯属娱乐!!!
感谢 **Defwebserver** 提供的实时示例,可在 http://silverlight.adefwebserver.com/alanbeasley/busybeesite/ 找到。(这只蜜蜂喝了苹果酒!)
一个更清晰的示例,展示了正在发生的事情,可在 http://silverlight.adefwebserver.com/alanbeasley/sillyshapes/SillyShapesSite/ 查看
本简短教程将展示如何使用 **Ken Johnson** 出色的 **Spirographic 文章** 来创建看似随机的运动,而无需编写一行代码! 我们还将首次在我的教程中介绍 **PathListBox**、**UserControls**、**Behaviours** 和 **Storyboards**。
之前的教程
- 第 1 课 - "制作更漂亮的按钮"
- 第 2 课 - "街机按钮"
- 第 3 课 - "相框控件"
- 第 4 课 - "最后一个制作按钮"
- 第 5 课 - "ListBox 样式 - 滚动条"
- 第 6 课 - "ListBox 样式 - 控件模板"
- 第 7 课 - "ListBox 样式 - 其他模板"
背景
随着 **Blend 4** 的发布,出现了新的 **PathListBox**,它允许“**路径到运动**”。这是 **Flash** 中已有的功能,到目前为止在 **Silverlight** 中一直缺失。基本上,这允许一个对象跟随另一个对象的线/路径。无论是一个正方形、一个圆形,还是任何其他矢量线/路径...
虽然这很棒,但也有其缺点,因为大多数易于绘制的形状都相当基础,不够复杂,无法模拟看似随机的运动。直到 **Ken Johnson** 的绝妙 **Spirographic 文章**!看过 Ken 的文章后,我问 Ken 是否有可能为创建的 **Spirographic** 形状添加一个 **Path Export** 功能。眨眼之间,它就有了!(再次感谢 Ken - 如果您还没有投票,请为您尚未投票的 Ken 的 **Spirographic 文章** 投票!!!)
Ken 所做的实际上是为 **Expression Blend** 和 **Silverlight** 创建了一整套新的 **Primitives**。我相信这可能/应该会导致这些 **Path** 形状的各种应用。我显然只是展示了一种可能性,但我相信还有许多许多其他的...
我一直渴望做一个涉及 **PathListBox** 的教程,而这是一个不容错过的绝佳机会。所以,虽然这个教程只是为了好玩,但我将展示如何使用 **PathListBox** 的基础知识来创建 **Silverlight** 中的基本动画。
开始吧
首先,我们需要在 **Blend** 中设置一个新的 **Silverlight** 项目,并将其命名为“**BusyBee**”。
接下来,我们需要一些东西沿 **Path** 移动,所以隆重推出明星“**Busy Dizzy Bee-sley**”(我)或简称 **BusyBee**。
从这里下载 **BusyBee UserControl**,并将两个文件添加到您的 **Project**。
接下来 **Rebuild** 您的 **Project**,使 **BusyBee** 在 **Blend** 中可用作 **Asset**。
从 **Assets** 菜单中选择 **BusyBee**,如下图所示
现在双击 **BusyBee UserControl** 将其添加到 **MainPage**。
接下来,我们需要将一些 **Spirographic** 形状添加到我们的项目中,所以请**点击此链接**以访问 Ken Johnson 的 **Spirographic 形状**。
选择 **Install**,如果一切顺利,您应该会看到与下图相同的屏幕
选择 **Shape Explorer**,它应该会显示下图中的屏幕
现在为 **BusyBee** 选择一个合适的 **Spirographic** 形状以供跟随。
*(我建议保持简单,并选择一个没有急转弯的形状作为 **BusyBee** 的主要 **Path** 进行跟随)。*
我选择了一个 **Rose**(玫瑰),值为 **A=10**、**N=4** 和 **D=3**,如下图所示
现在选择左上角的 **Export** 功能,然后选择 **Export Path XAML**,如下图所示
这将弹出一个窗口,显示此 **Spirographic** 形状的所有 **Path** 信息。
现在,将此信息输入 **Blend** 的最简单方法是 **复制** 引号 **""** 内的 **Path information** 数据到 **Clipboard**。
然后返回 **Blend**,在 **MainPage** 上插入一个 **Rectangle**,并将其转换为 **Path**。
现在选择 **XAML** 中的 **Path Data**,然后 **Paste** 粘贴 **Spirographic Path Data**。
在 **Artboard** 中,**Rectangle** 现在应该看起来像 **Spirographic** 形状,如下图所示
(为了清晰起见,我暂时隐藏了 **BusyBee**。)
在 **Objects and Timeline** 中,选择 **Path** 并将其重命名为“**BusyBeeMotionPath**”。
将 **Width** 和 **Height** 设置为 **240x240**,将 **Horizontal** 和 **Vertical Alignment** 设置为 **Center**。
这应该会将 **Spirographic** 形状居中放置在 **Artboard** 中,如下图所示
现在将一个 **PathListBox** 插入到 **Root** 中,并将 **BusyBee** 元素放置在 **PathListBox** 中,如下图所示
*(这使得 **BusyBee** 元素成为 **PathListBox** 的子项,并且 **PathListBox** 可以有多个子项。这些子项之间的间距由 **Padding** 控制,默认设置为 **10**)。*
现在选择 **PathListBox**,在 **LayoutPaths** 中,将“**BusyBeeMotionPath**”设置为子项 **BusyBee** 要跟随的 **LayoutPath**
在 **Artboard** 中,**BusyBee** 现在应该被放置在 **BusyBeeMotionPath** 的中心(起点)。
现在,将鼠标指针放在 **Layout Paths** 的 **Start** 部分,然后向右拖动。
这将使 **BusyBee** 沿 **BusyBeeMotionPath** 移动,在 **100%** 处到达 **Path** 的末尾。
运行应用程序并查看结果!什么都没发生!!!
这是因为我们没有用于动画过程的 **Storyboard**...
仍然选中 **PathListBox**,点击 **+** 图标将 **Storyboard** 添加到 **Project**。
将此 **Storyboard** 命名为“**BusyBeeMotion01**”并点击 **OK**。
这将在 **Objects and Timeline** 旁边打开一个 **Timeline**。(使用 **F6** 键在 **Blend** 中切换到 **Animation Layout**)。
转到 **Timeline** 上的 **12** 秒,在 **Layout Paths** 中,将 **Start** 设置为 **100%**。
**Play** 播放 **Animation**,在 **Artboard** 中,**BusyBee** 应该沿 **BusyBeeMotionPath** 移动,在 **12** 秒时到达 **100%**。
现在选择 **BusyBeeMotion01 Storyboard** 本身,如下图所示
在 **Properties** 选项卡中,将 **BusyBeeMotion01** 的 **RepeatBehaviour** 更改为“**Forever**”(永久),如下图所示
再次 **Run** 运行 **Application** 以查看结果,仍然什么都没发生!!!
这是因为当应用程序 **Run**(加载)时,**BusyBeeMotion01 Storyboard** 没有被触发(启动)。
所以我们需要设置一个 **Behaviour**,以便在 **Application** **Loaded**(加载)时启动 **BusyBeeMotion01 Storyboard**。
首先使用 **X** 关闭 **BusyBeeMotion01 Storyboard**,如下图所示
然后,在 **Assets** 选项卡中,选择 **Behaviours** 并找到 **ControlStoryboardAction Behaviour**。
点击并将 **ControlStoryboardAction** 拖动到 **PathListBox** 上,如下图所示
在 **Properties** 选项卡中,将 **EventName** 设置为“**Loaded**”,将 **Storyboard** 设置为“**BusyBeeMotion01**”,如下图所示
现在 **Run** 运行 **Application**,如果运气好的话,**BusyBee** 应该会跟随 **BusyBeeMotionPath**。
然而,“**Busy Dizzy Bee-sley**”(**BusyBee**)只面向左边,没有看向它要去的地方。(就像我开车一样!)
要改变这一点,让 **BusyBee** 在沿 **BusyBeeMotionPath** 移动时转向,我们需要将 **PathListBox** 的 **Orientation** 设置为“**OrientToPath**”。
**Run** 再次运行 **Application** 以查看结果。
**BusyBee**,或 **Busy Dizzy Bee-sley** 现在向后跑。(正是我开车的样子!)
所以选择 **BusyBee**,在 **Transform** 部分,沿 **X 轴** **Flip BusyBee**(翻转 BusyBee)。
**Run** 再次运行 **Application**,如果运气好的话,**BusyBee** 现在在跟随 **BusyBeeMotionPath** 时会面向正确的方向。
现在要使 **BusyBee** 的运动更加随机,我们可以通过让 **BusyBeeMotionPath** 跟随它自己的 **Motion Path** 来实现。
首先选择 **BusyBeeMotionPath** 和 **PathListBox**,然后选择 **Group Into > Grid**(组合成 > 网格)。
然后回到 Ken Johnson 的 **Spirographic 形状**,选择另一个形状作为 **Motion Path**。
我选择了一个 **Lissajous**(李萨如图形),值如下图所示
*(使用与之前相同的过程,将 **Path Data** 复制到一个 **Rectangle** 中,该 **Rectangle** 已在 **Blend 4** 中转换为 **Path**)。*
将这个新的 **Path** 重命名为“**ParentMotion**”,将 **Width** 和 **Height** 都设置为 **200**,并将 **Horizontal** 和 **Vertical Alignment** 设置为 **Center**。
插入一个新的 **PathListBox**,并将其重命名为“**ParentPathListBox**”。
选择 **Grid** 并将其放置在 **ParentPathListBox** 中,如下图所示
选择 **ParentPathListBox**,在 **Layout Paths** 部分,将“**ParentMotion**”设置为 **LayoutPaths**。
在 **Artboard** 中,**BusyBeeMotionPath** 现在已连接到 **ParentMotion**。
选择 **ParentPathListBox**,并创建一个名为“**BusyBeeParentMotion**”的新 **Storyboard**。
转到 **Timeline** 上的 **4.5** 秒,在 **Layout Paths** 中将 **Start** 更改为 **100%**。(完成后关闭 **Storyboard**)
接下来选择 **BusyBeeParentMotion** 并将 **RepeatBehaviour** 设置为 **Forever**。
然后将 **ControlStoryboardAction Behaviour** 拖动到 **ParentPathListBox** 上。
将 **EventName** 设置为“**Loaded**”,将 **Storyboard** 设置为“**BusyBeeParentMotion**”。
**Run** 运行 **Application** 并查看结果。
现在这看起来可能不太真实,因为 **Motion Paths** 干扰了 **BusyBee** 的运动。
所以选择 **BusyBeeMotionPath** 和 **ParentMotion Path**,移除它们的 **Fill**(填充)和 **Stroke**(描边)。
**Run** 再次运行 **Application** 以查看结果。
这有所改进,通过尝试不同的形状、调整 **Storyboard** 动画,以及可能使用更高级的父 **Path**,显然可以进行改进。
飞吧,Busy Dizzy Bee-sley,飞吧!
对我来说,还有最后一件事要做,那就是让 **Busy Dizzy Bee-sley**(**BusyBee**)的翅膀扇动起来。
所以在 **Project** 选项卡中,双击 **BusyBee**,在 **Artboard** 中打开这个 **UserControl**。
创建一个新的 **Storyboard**,命名为“**BusyBeeWingsFlap**”,然后点击 **OK**。
展开 **Tree** 以显示所有元素,并选择 **TopWing1、TopWing2、BottomWing1** 和 **BottomWing2**,如下图所示
现在在 **0.0** 秒处设置一个 **Keyframe**,将时间轴移动到 **0.4** 秒,并设置另一个 **Keyframe**。
将 **Timeline** 移动到 **0.2** 秒,然后选择“**TopWing1**”元素,如下图所示
在 Artboard 中,将 **Wing**(翅膀)的顶部向下拖动,使其看起来像下图
*(此编辑将自动为该元素生成一个 **Keyframe**,在 **0.2** 秒)。*
对剩余的 **3 个 Wings** 重复此过程,如下图所示
选择 **BusyBeeWingsFlap Storyboard** 本身,并将 **RepeatBehaviour** 设置为“**Forever**”。
关闭 **Storyboard**,然后将 **ControlStoryboardAction** 拖动到 **Layout Root**。
现在将 **EventName** 设置为“**Loaded**”,将 **Storyboard** 设置为“**BusyBeeWingsFlap**”。
**Run** 运行 **Application** 并查看结果。- **搞定!!!**
如果您喜欢这个有趣的练习,请 **VOTE!!!**(投票!!!)