Silverlight 中的自定义加载动画






4.67/5 (8投票s)
本指南介绍如何在 Silverlight 中为应用程序制作自定义加载动画。
在此处 查看所有变体的实时演示。并在此处 查看我博客上的原始帖子。
引言
在 上一篇文章 中,我展示了如何创建一个非常简单的导航控制器,它确实能控制导航。在本文中,我将介绍如何创建一个 Silverlight 加载器。
几乎所有包含某种数据的应用程序都需要一种方法来告知用户它正在工作并且没有冻结。随着 AJAX 网站/应用程序的兴起,网上有很多网站提供小的 GIF 动画供下载。其中一些甚至允许您选择颜色和尺寸。以下是一些这样的网站:
问题在于 Silverlight 不支持 GIF 图像。我猜他们认为不需要增加文件大小,因为 Silverlight 本身就有一个出色的动画引擎。当然,也有方法可以处理 GIF 图像(例如 CodePlex 上的 ImageTools),但我发现使用 XAML 创建它们非常有用,尤其是当您被要求将颜色增加一个字节或将某物向左移动 1 像素时。
我将向您展示如何创建几种不同类型的加载器。
代码
对于我们创建的每个加载器,我们将创建一个 UserControl
,其中包含一个 Storyboard
来执行动画,然后公开 Storyboard
内 DoubleAnimation
的某些属性。现在,对于我们制作的每个加载器,我们都会将此代码添加到代码文件中:
private EasingFunctionBase _easingFunction;
public EasingFunctionBase EasingFunction
{
get { return _easingFunction; }
set
{
_easingFunction = value;
foreach (Timeline anim in animStoryboard.Children)
{
if (anim is DoubleAnimation)
{
(anim as DoubleAnimation).EasingFunction = value;
}
else
{
if (anim is ColorAnimation)
{
(anim as ColorAnimation).EasingFunction = value;
}
else
{
if (anim is DoubleAnimationUsingKeyFrames)
{
foreach (DoubleKeyFrame key in (anim as
DoubleAnimationUsingKeyFrames).KeyFrames)
{
if (key is EasingDoubleKeyFrame)
{
(key as EasingDoubleKeyFrame).EasingFunction = value;
}
}
}
}
}
}
}
}
private RepeatBehavior _repeatBehavior;
public RepeatBehavior RepeatBehavior
{
get { return _repeatBehavior; }
set
{
_repeatBehavior = value;
foreach (Timeline anim in animStoryboard.Children)
{
anim.RepeatBehavior = value;
}
}
}
private Duration _duration;
public Duration Duration
{
get { return _duration; }
set
{
_duration = value;
foreach (Timeline anim in animStoryboard.Children)
{
anim.Duration = value;
}
}
}
private bool _autoReverse;
public bool AutoReverse
{
get { return _autoReverse; }
set
{
_autoReverse = value;
foreach (Timeline anim in animStoryboard.Children)
{
anim.AutoReverse = value;
}
}
}
private TimeSpan? _addToBeginTime;
public TimeSpan? AddToBeginTime
{
get { return _addToBeginTime; }
set
{
_addToBeginTime = value;
foreach (Timeline anim in animStoryboard.Children)
{
anim.BeginTime += value;
}
}
}
SwirlyCircles.xaml
我们要做的第一个是一个标准的旋转圆环。制作这些圆的最简单方法是使用 **Microsoft Expression Design**。下面,我将介绍一些基本步骤,以防您以前没有使用过它。如果您没有它,没关系 - 只需复制底部的 XAML 代码即可。
- 打开 Expression Design,然后单击 **文件 > 新建**,将 **宽度** 和 **高度** 设置为 **100px** 并确认。
- 现在,在工具栏中选择 **椭圆** 图标,然后单击并在画布上拖动以绘制一个圆(不要担心大小或位置)。
- 现在,在选中圆的情况下,更改底部工具栏中的值以正确地定位和调整它的大小。
- 在选中圆的情况下,复制并粘贴它。现在,将其定位在相同的位置,但放在底部。
- 按住 **Shift** 键,同时选择两者。然后复制(**Ctrl+C**)并原地粘贴(**Ctrl+F**)。
- 再次,按住 **Shift** 键,将鼠标光标放在角落块的外面,然后单击并向下拖动以将其旋转成对角线。
- 执行第 5 步和第 6 步两次,这样您就有了一个完整的圆环。
- 现在您可以选择所有圆并根据喜好在右侧工具栏中为它们着色。
- 最后,在它们仍被选中时,单击 **编辑 > 复制 XAML**。
完成这些之后,您可以继续向您的项目添加一个名为 SwirlyCircles.xaml 的新 UserControl
。将我们之前提到的代码添加到 .cs 文件中。然后转到 XAML 文件并粘贴您从 Expression Design 复制的 XAML。
<!--I removed some attributes from the Canvas tag that weren't needed-->
<Canvas Width="100" Height="100">
<Ellipse Width="13.25" Height="13.25"
Canvas.Left="43.4583"
Canvas.Top="7.62939e-006"
Stretch="Fill">
<Ellipse.Fill>
<RadialGradientBrush RadiusX="0.5"
RadiusY="0.5" Center="0.5,0.5"
GradientOrigin="0.5,0.5">
<RadialGradientBrush.GradientStops>
<GradientStop Color="#FFFF0000" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
</RadialGradientBrush.GradientStops>
<RadialGradientBrush.RelativeTransform>
<TransformGroup/>
</RadialGradientBrush.RelativeTransform>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<Ellipse Width="14" Height="14"
Canvas.Left="43"
Canvas.Top="7.62939e-006" Stretch="Fill">
<Ellipse.Fill>
<RadialGradientBrush RadiusX="0.5"
RadiusY="0.499999"
Center="0.5,0.499999"
GradientOrigin="0.5,0.499999">
<RadialGradientBrush.GradientStops>
<GradientStop Color="#FFFF0000" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
</RadialGradientBrush.GradientStops>
<RadialGradientBrush.RelativeTransform>
<TransformGroup/>
</RadialGradientBrush.RelativeTransform>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<Ellipse Width="14" Height="14"
Canvas.Left="43" Canvas.Top="86"
Stretch="Fill">
<Ellipse.Fill>
<RadialGradientBrush RadiusX="0.500001"
RadiusY="0.499999"
Center="0.5,0.499999"
GradientOrigin="0.5,0.499999">
<RadialGradientBrush.GradientStops>
<GradientStop Color="#FFFF0000" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
</RadialGradientBrush.GradientStops>
<RadialGradientBrush.RelativeTransform>
<TransformGroup/>
</RadialGradientBrush.RelativeTransform>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<Path Width="14" Height="14"
Canvas.Left="73.4056" Canvas.Top="12.5944"
Stretch="Fill"
Data="F1 M 85.3553,14.6447C 88.089,17.3783 88.089,
21.8105 85.3553,24.5442C 82.6217,27.2778 78.1895,
27.2778 75.4558,24.5442C 72.7222,21.8105 72.7222,
17.3783 75.4558,14.6447C 78.1895,11.911 82.6217,
11.911 85.3553,14.6447 Z ">
<Path.Fill>
<RadialGradientBrush RadiusX="0.5"
RadiusY="0.499999"
Center="0.500001,0.5"
GradientOrigin="0.500001,0.5">
<RadialGradientBrush.GradientStops>
<GradientStop Color="#FFFF0000" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
</RadialGradientBrush.GradientStops>
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<RotateTransform CenterX="0.500001"
CenterY="0.5" Angle="45"/>
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
</RadialGradientBrush>
</Path.Fill>
</Path>
<Path Width="14" Height="14"
Canvas.Left="12.5944" Canvas.Top="73.4056"
Stretch="Fill"
Data="F1 M 24.5442,75.4558C 27.2778,78.1895 27.2778,
82.6217 24.5442,85.3553C 21.8105,88.089 17.3783,
88.089 14.6447,85.3553C 11.911,82.6217 11.911,
78.1895 14.6447,75.4558C 17.3783,72.7222 21.8105,
72.7222 24.5442,75.4558 Z ">
<Path.Fill>
<RadialGradientBrush RadiusX="0.5"
RadiusY="0.5" Center="0.5,0.5"
GradientOrigin="0.5,0.5">
<RadialGradientBrush.GradientStops>
<GradientStop Color="#FFFF0000" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
</RadialGradientBrush.GradientStops>
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<RotateTransform CenterX="0.5"
CenterY="0.5" Angle="45"/>
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
</RadialGradientBrush>
</Path.Fill>
</Path>
<Ellipse Width="14" Height="14"
Canvas.Left="86" Canvas.Top="43"
Stretch="Fill">
<Ellipse.Fill>
<RadialGradientBrush RadiusX="0.5"
RadiusY="0.5" Center="0.5,0.5"
GradientOrigin="0.5,0.5">
<RadialGradientBrush.GradientStops>
<GradientStop Color="#FFFF0000" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
</RadialGradientBrush.GradientStops>
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<RotateTransform CenterX="0.5"
CenterY="0.5" Angle="90"/>
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<Ellipse Width="14" Height="14"
Canvas.Left="2.73207e-006"
Canvas.Top="43" Stretch="Fill">
<Ellipse.Fill>
<RadialGradientBrush RadiusX="0.5"
RadiusY="0.499999" Center="0.500001,0.5"
GradientOrigin="0.500001,0.5">
<RadialGradientBrush.GradientStops>
<GradientStop Color="#FFFF0000" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
</RadialGradientBrush.GradientStops>
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<RotateTransform CenterX="0.500001"
CenterY="0.5" Angle="90"/>
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<Path Width="14" Height="14"
Canvas.Left="73.4056" Canvas.Top="73.4056"
Stretch="Fill"
Data="F1 M 85.3553,85.3553C 82.6217,88.089 78.1895,
88.089 75.4558,85.3553C 72.7222,82.6217 72.7222,
78.1895 75.4558,75.4558C 78.1895,72.7222 82.6217,
72.7222 85.3553,75.4558C 88.089,78.1895 88.089,
82.6217 85.3553,85.3553 Z ">
<Path.Fill>
<RadialGradientBrush RadiusX="0.5"
RadiusY="0.499999" Center="0.5,0.500001"
GradientOrigin="0.5,0.500001">
<RadialGradientBrush.GradientStops>
<GradientStop Color="#FFFF0000" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
</RadialGradientBrush.GradientStops>
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<RotateTransform CenterX="0.5"
CenterY="0.500001" Angle="135"/>
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
</RadialGradientBrush>
</Path.Fill>
</Path>
<Path Width="14" Height="14"
Canvas.Left="12.5944" Canvas.Top="12.5944"
Stretch="Fill"
Data="F1 M 24.5442,24.5442C 21.8105,27.2778 17.3783,
27.2778 14.6447,24.5442C 11.911,21.8105 11.911,
17.3783 14.6447,14.6447C 17.3783,11.911 21.8105,
11.911 24.5442,14.6447C 27.2778,17.3783 27.2778,
21.8105 24.5442,24.5442 Z ">
<Path.Fill>
<RadialGradientBrush RadiusX="0.5"
RadiusY="0.5" Center="0.5,0.5"
GradientOrigin="0.5,0.5">
<RadialGradientBrush.GradientStops>
<GradientStop Color="#FFFF0000" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
</RadialGradientBrush.GradientStops>
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<RotateTransform CenterX="0.5"
CenterY="0.5" Angle="135"/>
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
</RadialGradientBrush>
</Path.Fill>
</Path>
</Canvas>
现在,就在 Canvas
的结束标签上方,我们将为其设置一个 **Render Transform** 来旋转它 - 因为这个加载器将只是旋转圆。
<Canvas.RenderTransform>
<RotateTransform x:Name="rotateTransform"
CenterX="50" CenterY="50" />
</Canvas.RenderTransform>
该 RotateTransform
具有一个 Angle
属性,该属性是一个从 0 到 360 度的双精度数。为了控制它,我们将需要一个 storyboard。要在控件加载时运行 storyboard,我们可以调用构造函数中的 .Begin();
。但更简单的方法是使用 **Trigger**,它会在控件触发其 Loaded
事件后立即启动 storyboard。这很简单。将此添加到 Canvas
的结束标签正上方:
<Canvas.Triggers>
<EventTrigger RoutedEvent="UserControl.Loaded">
<BeginStoryboard>
<Storyboard x:Name="animStoryboard">
<DoubleAnimation Duration="00:00:03"
To="360" RepeatBehavior="Forever"
Storyboard.TargetName="rotateTransform"
Storyboard.TargetProperty="Angle"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
要查看结果,请先构建项目,然后转到 MainPage.xaml 并从左侧的工具箱中拖入您的加载器控件。它将显示如下:
<my:SwirlyCircles />
如果您还记得第一个代码块,有许多与我们公开的 DoubleAnimation
相关的属性。我们可以在 MainPage.xaml 中或在使用该控件的任何地方进行设置,如下所示:
<my:SwirlyCircles AutoReverse="True"
Duration="00:00:05" AddToBeginTime="00:00:00">
<my:SwirlyCircles.EasingFunction>
<BounceEase />
</my:SwirlyCircles.EasingFunction>
</my:SwirlyCircles>
需要注意的一点是,默认情况下,默认 Grid
控件的 Background
属性是 White
。确保删除它或将其设置为 Transparent
,以免在加载器周围出现白色块。
运行项目时,您将看到如下内容:
LittleBoxes.xaml
制作这个,步骤与第一个基本相同,所以我不会再详细介绍了。只需添加一个新的 UserControl
,并在 .cs 文件中放入那些属性。然后设置其外观以及动画,将其放入现有的 Grid
中:
<Canvas Width="100" Height="40">
<Border x:Name="border1" Width="10" Height="10"
Canvas.Left="0" CornerRadius="5"
Background="#FF2B8EA0"/>
<Border x:Name="border2" Width="10"
Height="10" Canvas.Left="10"
CornerRadius="5" Background="#FF2B8EA0" />
<Border x:Name="border3" Width="10"
Height="10" Canvas.Left="20"
CornerRadius="5" Background="#FF2B8EA0" />
<Border x:Name="border4" Width="10"
Height="10" Canvas.Left="30"
CornerRadius="5" Background="#FF2B8EA0" />
<Border x:Name="border5" Width="10"
Height="10" Canvas.Left="40"
CornerRadius="5" Background="#FF2B8EA0" />
<Border x:Name="border6" Width="10"
Height="10" Canvas.Left="50"
CornerRadius="5" Background="#FF2B8EA0" />
<Border x:Name="border7" Width="10"
Height="10" Canvas.Left="60"
CornerRadius="5" Background="#FF2B8EA0" />
<Border x:Name="border8" Width="10"
Height="10" Canvas.Left="70"
CornerRadius="5" Background="#FF2B8EA0" />
<Border x:Name="border9" Width="10"
Height="10" Canvas.Left="80"
CornerRadius="5" Background="#FF2B8EA0" />
<Border x:Name="border10" Width="10"
Height="10" Canvas.Left="90"
CornerRadius="5" Background="#FF2B8EA0" />
<Canvas.Triggers>
<EventTrigger RoutedEvent="UserControl.Loaded">
<BeginStoryboard>
<Storyboard x:Name="animStoryboard"
Storyboard.TargetProperty="(Canvas.Top)">
<DoubleAnimation Storyboard.TargetName="border1"
To="30" BeginTime="00:00:00.1"
Duration="00:00:00.5"
AutoReverse="True" RepeatBehavior="Forever"/>
<DoubleAnimation Storyboard.TargetName="border2"
To="30" BeginTime="00:00:00.2"
Duration="00:00:00.5" AutoReverse="True"
RepeatBehavior="Forever"/>
<DoubleAnimation Storyboard.TargetName="border3"
To="30" BeginTime="00:00:00.3"
Duration="00:00:00.5" AutoReverse="True"
RepeatBehavior="Forever"/>
<DoubleAnimation Storyboard.TargetName="border4"
To="30" BeginTime="00:00:00.4"
Duration="00:00:00.5" AutoReverse="True"
RepeatBehavior="Forever"/>
<DoubleAnimation Storyboard.TargetName="border5"
To="30" BeginTime="00:00:00.5"
Duration="00:00:00.5" AutoReverse="True"
RepeatBehavior="Forever"/>
<DoubleAnimation Storyboard.TargetName="border6"
To="30" BeginTime="00:00:00.6"
Duration="00:00:00.5" AutoReverse="True"
RepeatBehavior="Forever"/>
<DoubleAnimation Storyboard.TargetName="border7"
To="30" BeginTime="00:00:00.7"
Duration="00:00:00.5" AutoReverse="True"
RepeatBehavior="Forever"/>
<DoubleAnimation Storyboard.TargetName="border8"
To="30" BeginTime="00:00:00.8"
Duration="00:00:00.5" AutoReverse="True"
RepeatBehavior="Forever"/>
<DoubleAnimation Storyboard.TargetName="border9"
To="30" BeginTime="00:00:00.9"
Duration="00:00:00.5" AutoReverse="True"
RepeatBehavior="Forever"/>
<DoubleAnimation Storyboard.TargetName="border10"
To="30" BeginTime="00:00:01"
Duration="00:00:00.5" AutoReverse="True"
RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
</Canvas>
结果如下
WP7.xaml
我非常喜欢 Windows Phone 7 加载器,所以这个与之类似。由于动画非常具体,您可能想省略一些属性。
<Canvas Width="200" Height="7">
<Rectangle x:Name="rect1" Width="7" Height="7"
Fill="#EE00ABA9" Stroke="Black" />
<Rectangle x:Name="rect2" Width="7" Height="7"
Fill="#EE00ABA9" Stroke="Black" />
<Rectangle x:Name="rect3" Width="7" Height="7"
Fill="#EE00ABA9" Stroke="Black" />
<Rectangle x:Name="rect4" Width="7" Height="7"
Fill="#EE00ABA9" Stroke="Black" />
<Rectangle x:Name="rect5" Width="7" Height="7"
Fill="#EE00ABA9" Stroke="Black" />
<Canvas.Triggers>
<EventTrigger RoutedEvent="UserControl.Loaded">
<BeginStoryboard>
<Storyboard SpeedRatio="1.5"
x:Name="animStoryboard"
Storyboard.TargetProperty="(Canvas.Left)">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Duration="00:00:03"
Storyboard.TargetName="rect1"
RepeatBehavior="Forever">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="80">
<EasingDoubleKeyFrame.EasingFunction>
<QuinticEase EasingMode="EaseOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:03" Value="200">
<EasingDoubleKeyFrame.EasingFunction>
<QuinticEase EasingMode="EaseIn" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.1"
Duration="00:00:03"
Storyboard.TargetName="rect2"
RepeatBehavior="Forever">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="80">
<EasingDoubleKeyFrame.EasingFunction>
<QuinticEase EasingMode="EaseOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:03" Value="200">
<EasingDoubleKeyFrame.EasingFunction>
<QuinticEase EasingMode="EaseIn" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.2"
Duration="00:00:03"
Storyboard.TargetName="rect3"
RepeatBehavior="Forever">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="80">
<EasingDoubleKeyFrame.EasingFunction>
<QuinticEase EasingMode="EaseOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:03" Value="200">
<EasingDoubleKeyFrame.EasingFunction>
<QuinticEase EasingMode="EaseIn" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.3"
Duration="00:00:03"
Storyboard.TargetName="rect4"
RepeatBehavior="Forever">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="80">
<EasingDoubleKeyFrame.EasingFunction>
<QuinticEase EasingMode="EaseOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:03" Value="200">
<EasingDoubleKeyFrame.EasingFunction>
<QuinticEase EasingMode="EaseIn" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.4"
Duration="00:00:03"
Storyboard.TargetName="rect5"
RepeatBehavior="Forever">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="80">
<EasingDoubleKeyFrame.EasingFunction>
<QuinticEase EasingMode="EaseOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:03" Value="200">
<EasingDoubleKeyFrame.EasingFunction>
<QuinticEase EasingMode="EaseIn" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Duration="00:00:03" RepeatBehavior="Forever"
Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="rect1">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:03" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.1"
Duration="00:00:03" RepeatBehavior="Forever"
Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="rect2">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:03" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.2"
Duration="00:00:03" RepeatBehavior="Forever"
Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="rect3">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:03" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.3"
Duration="00:00:03" RepeatBehavior="Forever"
Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="rect4">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:03" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00.4"
Duration="00:00:03" RepeatBehavior="Forever"
Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="rect5">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="00:00:03" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
</Canvas>
它不完全相同,但与手机上的那个类似。将其包含在 MainPage.xaml 或其他地方后,您将得到这个:
3D.xaml
好的,这实际上不是 3D,但我们有这个想法。发生的情况是圆圈从左到右移动,然后又回到左边。在从左到右的过程中,宽度和高度从 7px 变为 10px 再回到 7px,然后从右到左,从 7px 变为 0px 再回到 7px 以重新开始循环。这使得它看起来有点像回到了太空。
<Canvas Width="100" Height="10">
<Border x:Name="border1" Width="10" Height="10"
Canvas.Left="0" CornerRadius="5" Background="#EE00ABA9"/>
<Border x:Name="border2" Width="10" Height="10"
Canvas.Left="0" CornerRadius="5" Background="#EE00ABA9"/>
<Border x:Name="border3" Width="10" Height="10"
Canvas.Left="0" CornerRadius="5" Background="#EE00ABA9"/>
<Border x:Name="border4" Width="10" Height="10"
Canvas.Left="0" CornerRadius="5" Background="#EE00ABA9"/>
<Canvas.Triggers>
<EventTrigger RoutedEvent="UserControl.Loaded">
<BeginStoryboard>
<Storyboard x:Name="animStoryboard">
<DoubleAnimationUsingKeyFrames Duration="00:00:01"
BeginTime="00:00:00" RepeatBehavior="Forever"
Storyboard.TargetName="border1"
Storyboard.TargetProperty="Width">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="7"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.25" Value="10"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="7"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.75" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="7"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Duration="00:00:01"
BeginTime="00:00:00" RepeatBehavior="Forever"
Storyboard.TargetName="border1"
Storyboard.TargetProperty="Height">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="7"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.25" Value="10"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="7"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.75" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="7"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Duration="00:00:01"
BeginTime="00:00:00" RepeatBehavior="Forever"
Storyboard.TargetName="border1"
Storyboard.TargetProperty="(Canvas.Left)">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0" >
<EasingDoubleKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="90">
<EasingDoubleKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Duration="00:00:01"
BeginTime="00:00:00.1" RepeatBehavior="Forever"
Storyboard.TargetName="border2"
Storyboard.TargetProperty="Width">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="7"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.25" Value="10"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="7"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.75" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="7"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Duration="00:00:01"
BeginTime="00:00:00.1" RepeatBehavior="Forever"
Storyboard.TargetName="border2"
Storyboard.TargetProperty="Height">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="7"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.25" Value="10"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="7"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.75" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="7"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Duration="00:00:01"
BeginTime="00:00:00.1" RepeatBehavior="Forever"
Storyboard.TargetName="border2"
Storyboard.TargetProperty="(Canvas.Left)">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0" >
<EasingDoubleKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="90">
<EasingDoubleKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Duration="00:00:01"
BeginTime="00:00:00.2" RepeatBehavior="Forever"
Storyboard.TargetName="border3"
Storyboard.TargetProperty="Width">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="7"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.25" Value="10"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="7"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.75" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="7"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Duration="00:00:01"
BeginTime="00:00:00.2" RepeatBehavior="Forever"
Storyboard.TargetName="border3"
Storyboard.TargetProperty="Height">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="7"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.25" Value="10"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="7"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.75" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="7"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Duration="00:00:01"
BeginTime="00:00:00.2" RepeatBehavior="Forever"
Storyboard.TargetName="border3"
Storyboard.TargetProperty="(Canvas.Left)">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0" >
<EasingDoubleKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="90">
<EasingDoubleKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Duration="00:00:01"
BeginTime="00:00:00.3" RepeatBehavior="Forever"
Storyboard.TargetName="border4"
Storyboard.TargetProperty="Width">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="7"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.25" Value="10"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="7"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.75" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="7"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Duration="00:00:01"
BeginTime="00:00:00.3" RepeatBehavior="Forever"
Storyboard.TargetName="border4"
Storyboard.TargetProperty="Height">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="7"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.25" Value="10"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="7"/>
<EasingDoubleKeyFrame KeyTime="00:00:00.75" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="7"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Duration="00:00:01"
BeginTime="00:00:00.3" RepeatBehavior="Forever"
Storyboard.TargetName="border4"
Storyboard.TargetProperty="(Canvas.Left)">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0" >
<EasingDoubleKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="90">
<EasingDoubleKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="00:00:01" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
</Canvas>
很难从静态图片中看出它实际的样子,但在这里:
结论
我只展示了一些示例供您开始,但每个应用程序都会有所不同,需要不同的东西。所以可以多尝试一下。如果您遵循了上一篇文章,那么您可以将其中任何一个放入加载器容器中。
请务必在此处 访问演示页面以查看所有变体的实际运行效果。并在此处 查看我博客上的原始帖子。
历史
- 2011/2/20 - 原始帖子。