概述
UWP Community Toolkit 中有一个 Animations 的集合,它们可以帮助开发者实现很多的动画,本篇我们先来看一下 Animations 的功能都有哪些,再后面会针对每一种 Animations 做详细的代码分析。
Animations 集合涵盖了很多种类的动画,我们先来看一下官方示例的截图:
下面我们分别来看一下每一种动画的调用过程和展示效果。
调用示例
1. Blur
模糊动画,可以通过增加或减少像素尺寸来使 XAML 元素变模糊,可以应用在所有 XAML 元素上,不影响控件的功能本身。
来看一个简单的调用示例:
我们针对一张图片做 Blur 处理,动画开始前如图一所示,动画后如图二所示;
<Page ... xmlns:interactivity="using:Microsoft.Xaml.Interactivity" xmlns:behaviors="using:Microsoft.Toolkit.Uwp.UI.Animations.Behaviors"> ... <Border Background="Gray" Width="400" Height="300"> <Image x:Name="ToolkitLogo" Source="ms-appx:///Assets/01.jpg" Height="300" Width="400" /> <interactivity:Interaction.Behaviors> <behaviors:Blur x:Name="BlurBehavior" Value="1" Duration="3000" Delay="0" EasingType="Linear" AutomaticallyStart="True"/> </interactivity:Interaction.Behaviors> </Border>
using Microsoft.Toolkit.Uwp.UI.Animations; ... , duration: , delay: ).StartAsync();
2. Connected Animations
连接动画,可以通过让一个元素在两种不同视图的动画来创建一个动态并且引人注目的导航体验。连接动画的 XAML 附加属性可以通过简单的添加允许动画的元素键值来在 XAML 中直接定义,同样定位动画和 lists 中的动画也可以通过附加属性来定义。简单来说,就是在页面导航时,指定导航前和导航后的元素,让后者在前者的位置开始做动画,平移至最后的位置,这会让页面导航更加动态和丰富;
几个重要的属性:
- Connected.Key - 通过 ConnectedAnimationsService 来注册元素,为了让动画生效,导航前后页面的元素必须使用同一个键值;导航后页面的对应元素会从导航前页面元素的位置开始动画;
- Connected.AnchorElement - 为了启用 Connected Animation,在应该和 Connected Animation 元素并肩出现的元素上使用 AnchorElement 附加属性;
- Connected.ListItemKey - 为 ListView 或 GridView 注册 Connected Animation,当页面导航中使用了这个属性,那么导航后页面的对应元素,会根据导航传入的参数,选择 List 中选中的元素作为动画基准进行动画;必须配合 Connected.ListItemElementName 属性来使用。
- Connected.ListItemElementName - 指定 item 的 DateTemplate 中对应名字的元素应该执行动画,必须配合 Connected.ListItemKey 属性来使用;
来看一个简单的调用示例:
我们有三个页面,第一个页面指定一个按钮,第二个页面的 Header 元素指定从按钮开始动画,第三个页面根据第二个页面选择的元素开始动画;
第一个页面代码:
指定 Connected.Key,定义 Navigate 操作;
<Button Click="Button_Click" Content="Start Connected Animations" animations:Connected.Key="item" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="20"/>
this.Frame.Navigate(typeof(MainPage));
第二个页面代码:
指定 Connected.Key,Connected.AnchorElement,Connected.ListItemElementName 和 Connected.ListItemKey,定义 Navigate 操作,传入当前点击元素;
<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal"> <Border x:Name="HeroElement" Height="300" Width="300" Background="Purple" animations:Connected.Key="item"></Border> <StackPanel x:Name="HeroDetailsElement" Margin="20,0" VerticalAlignment="Bottom" MaxWidth="500" animations:Connected.AnchorElement="{x:Bind HeroElement}"> <TextBlock Text="Header" FontSize="50"></TextBlock> <TextBlock TextWrapping="WrapWholeWords">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce eleifend ex sit amet blandit lobortis. Curabitur ut diam fringilla, interdum massa sit amet, facilisis erat. Donec vulputate sed ex vel pellentesque. In sodales odio non felis interdum viverra. Morbi in mi mollis, ullamcorper nibh sit amet, sagittis ex. Maecenas dapibus commodo venenatis. Donec at egestas est.</TextBlock> </StackPanel> </StackPanel> <GridView x:Name="listView" Margin="0, 40, 0, 0" SelectionMode="None" Grid.Row="1" ItemClick="listView_ItemClick" IsItemClickEnabled="True" animations:Connected.ListItemElementName="ItemThumbnail" animations:Connected.ListItemKey="listItem"> <GridView.ItemTemplate .../ > </GridView> </Grid>
Frame.Navigate(typeof(ThirdPage), e.ClickedItem);
第三个页面代码:
指定 Connected.AnchorElement 和 Connected.Key,定义 OnNavigatedTo 事件接受第二个页面传递的参数;
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> <StackPanel x:Name="HeroDetailsElement" Margin="20,0" VerticalAlignment="Bottom" MaxWidth="500" animations:Connected.AnchorElement="{x:Bind ItemHeroElement}"> <TextBlock Text="Test" FontSize="50"></TextBlock> <TextBlock TextWrapping="WrapWholeWords">...</TextBlock> </StackPanel> <Border x:Name="ItemHeroElement" Height="300" Width="300" Background="Purple" animations:Connected.Key="listItem"></Border> </StackPanel> <TextBlock x:Name="Content" Margin="0,40" TextWrapping="WrapWholeWords" > ...</TextBlock>
item = e.Parameter as DataItem; base.OnNavigatedTo(e);
3. Fade
淡入淡出动画,可以随着时间的推移对 XAML 元素进行淡入淡出的动画处理,不会影响元素本身的功能;
来看一个简单的调用示例:
我们针对一张图片做 Fade 处理,动画开始前如图一所示,动画后如图二所示;
<Border Background="Gray" Width="400" Height="300"> <Image x:Name="ToolkitLogo" Source="ms-appx:///Assets/01.jpg" Height="400" Width="300" > <interactivity:Interaction.Behaviors> <behaviors:Fade x:Name="Fade" Value="0" Duration="1000" Delay="2000" EasingType="Linear" AutomaticallyStart="False"/> </interactivity:Interaction.Behaviors> </Image> </Border>
4. FadeHeader
Header 淡入淡出动画可以在滚动时让 ListView 和 GridView 的 Header 元素实现淡入淡出,当 Header 达到显示边界的时候,透明度渐变为 0;
来看一个简单的调用示例:
我们创建了一个 GridView 控件,指定它的 Header 执行 FadeHeader 动画,可以看到当没有滚动时,Header 是蓝色没有透明度变化;当滚动到约一半位置时,Header 执行动画导致透明度变低,有淡出效果;
<GridView x:Name="listView" Margin="0, 40, 0, 0" SelectionMode="None" Grid.Row="1"> <interactivity:Interaction.Behaviors> <behaviors:FadeHeaderBehavior /> </interactivity:Interaction.Behaviors> <GridView.Header> <Grid x:Name="MyHeaderGrid" MinHeight="250" Background="Blue"> <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center"> <TextBlock Text="This Is The Header" TextAlignment="Center" FontWeight="Bold" FontSize="48" Foreground="White" Margin="12" /> <TextBlock Text="It starts with 100% opacity but will fade to 0% as you scroll up." Foreground="White" Margin="12,0,12,12" VerticalAlignment="Center" TextAlignment="Center" /> </StackPanel> </Grid> </GridView.Header> ... </GridView/>
5. Implicit Animations
隐式动画,是一种合成动画,用于在属性变化时描述动画应该怎么和何时发生,比如透明度和偏移。Show 和 Hide 动画用于描述在元素可见属性改变时的动画;使用附加属性可以在 XAML 中进行定义,包括 XAML resources 和 element;而且它可以和我们前面说过的 VisualExtensions 一起使用。
以下几个重要属性需要关注:
- Implicit.Animations - 制定一个动画集合,当属性变化时会执行动画;如果一个动画集合不包含 keyFrame 信息,则这个动画会被定义为一个针对 Target 的动画,当 Target 对应属性变化时,会触发这个动画从现有值到变化后的值的动画;当动画包含 ImplicitTarget 属性时,当可视化属性变化时会触发动画;动画需要指定 To From 动画属性;
- Implicit.ShowAnimations and Implicit.HideAnimations - 当元素添加或删除,或者 Visibility 变化时触发;
来看一个简单的调用示例:
我们对 Border 执行 Implicit 动画,看一下包含了哪些组合的动画:Show 动画,包括平移和透明度变化;Hide 动画类似;以及 Animations,包含三种不同的动画,一是针对 Target Offset 的动画,二是针对 ImplicitTarget Offset 的动画,三是针对 Target Scale 的动画;我们操作让 Border 隐藏和显示,看一下动画效果:
<Canvas> <Border x:Name="Element" Height="100" Width="100" Background="Red" Canvas.Top="100" Canvas.Left="100" extensions:VisualEx.CenterPoint="50,50,0"> <animations:Implicit.ShowAnimations> <animations:TranslationAnimation Duration="0:0:1" From="0, -200, 0" To="0" ></animations:TranslationAnimation> <animations:OpacityAnimation Duration="0:0:1" From="0" To="1.0"></animations:OpacityAnimation> </animations:Implicit.ShowAnimations> <animations:Implicit.HideAnimations> <animations:ScalarAnimation Target="Opacity" Duration="0:0:1" To="0.0"></animations:ScalarAnimation> <animations:ScalarAnimation Target="Translation.Y" Duration="0:0:1" To="-200"> <animations:ScalarKeyFrame Key="0.1" Value="30"></animations:ScalarKeyFrame> <animations:ScalarKeyFrame Key="0.5" Value="0.0"></animations:ScalarKeyFrame> </animations:ScalarAnimation> </animations:Implicit.HideAnimations> <animations:Implicit.Animations> <!-- Notice this animation does not have a From/To value or any KeyFrames. In this case, an ExpressionKeyFrame will be added of Value=this.FinalValue --> <animations:Vector3Animation Target="Offset" Duration="0:0:1"></animations:Vector3Animation> <!-- Notice this animation specifies an ImplicitTarget different from Target. In this case, the animation will run when the Offset is changed --> <animations:ScalarAnimation Target="RotationAngleInDegrees" ImplicitTarget="Offset" Duration="0:0:1.2" From="0" To="0"> <animations:ScalarKeyFrame Key="0.9" Value="80"></animations:ScalarKeyFrame> </animations:ScalarAnimation> <animations:Vector3Animation Target="Scale" Duration="0:0:1"></animations:Vector3Animation> </animations:Implicit.Animations> </Border> </Canvas>
6. Light
光效动画,展示了一个点光源出现在元素中间的动画效果;distance 属性决定了光源的亮度,光源越近,元素越暗;
几个重要属性需要关注:
- Distance - 点光源的距离,0 是最远的;
- Color - 点光源的颜色画刷;
来看一个简单的调用示例:
在 Logo 图片上实现一个 Light Animation,DIstance 是 10,Color 是红色;
<Image x:Name="logo" Source="ms-appx:///Assets/LockScreenLogo.scale-200.png" Height="100" Width="100" > <interactivity:Interaction.Behaviors> <behaviors:Light x:Name="LightBehavior" Distance="10" Duration="500" Delay="0" AutomaticallyStart="False" EasingType="Linear" Color="Red" /> </interactivity:Interaction.Behaviors> </Image>
7. Offset
偏移动画,用于把控件从一个地方移动到另一个地方,也是应用于所有的 XAML 元素,不影响控件本身的功能;
其中 EasingType 需要重点关注,它会决定偏移动画的动画形式,具体的动画类型可以在这里看到:Offset Animation - Easing Type.
来看一个简单的调用示例:
我们让一个 Image X 和 Y 方向都偏移 25 像素,EasingType 是 Elastic;看下动画效果。
<Image x:Name="logo" Source="ms-appx:///Assets/LockScreenLogo.scale-200.png" Height="100" Width="100" > <interactivity:Interaction.Behaviors> <behaviors:Offset x:Name="OffsetBehavior" OffsetX="25.0" OffsetY="25.0" Duration="2500" Delay="250" EasingType="Elastic" AutomaticallyStart="True"/> </interactivity:Interaction.Behaviors> </Image>
8. ReorderGridAnimation
Grid 重排序动画,当 GridView 尺寸变化时,ReorderGridAnimation 动画可以让元素通过动画移动到新的位置;只需要在 GridView 中通过附加属性指定 ReorderGridAnimation 的 Duration 就可以实现动画的定义;
来看一个简单的调用示例:
<GridView x:Name="ImageView" animations:ReorderGridAnimation.Duration="100"> <GridView.ItemTemplate> <DataTemplate> <Image Width="200" Height="200" Source="{Binding Thumbnail}" Stretch="UniformToFill" /> </DataTemplate> </GridView.ItemTemplate> </GridView>
9. Rotate
旋转动画允许用户修改和定义控件旋转动画,也是应用于所有的 XAML 元素,不影响控件本身的功能;
其中 EasingType 需要重点关注,它会决定旋转动画的动画形式,具体的动画类型可以在这里看到:Rotate Animation - Easing Type.
来看一个简单的调用示例:
<Border Background="Gray" Width="400" Height="300"> <Image x:Name="logo" Source="ms-appx:///Assets/01.jpg" Height="400" Width="300" > <interactivity:Interaction.Behaviors> <behaviors:Rotate x:Name="Rotate" Value="100" CenterX="200" CenterY="150" Duration="2000" Delay="0" EasingType="Linear" AutomaticallyStart="True"/> </interactivity:Interaction.Behaviors> </Image> </Border>
10. Saturation
饱和度动画可以有选择的对 XAML 元素的饱和度执行动画,也是应用于所有的 XAML 元素,不影响控件本身的功能;
来看一个简单的调用示例:
<Border Background="Gray" Width="400" Height="300"> <Image x:Name="logo" Source="ms-appx:///Assets/01.jpg" Height="400" Width="300" > <interactivity:Interaction.Behaviors> <behaviors:Saturation x:Name="SaturationBehavior" Value="0.24" Duration="3000" Delay="0" EasingType="Linear" AutomaticallyStart="True"/> </interactivity:Interaction.Behaviors> </Image> </Border>
11. Scale
缩放动画允许用户修改和定义控件缩放动画,也是应用于所有的 XAML 元素,不影响控件本身的功能;
其中 EasingType 需要重点关注,它会决定缩放动画的动画形式,具体的动画类型可以在这里看到:Scale Animation - Easing Type.
来看一个简单的调用示例:
<Border Background="Gray" Width="400" Height="300"> <Image x:Name="logo" Source="ms-appx:///Assets/01.jpg" Height="400" Width="300" > <interactivity:Interaction.Behaviors> <behaviors:Scale x:Name="Scale" ScaleX="0.53" ScaleY="0.31" CenterX="200" CenterY="150" Duration="2000" EasingType="Linear" AutomaticallyStart="True"/> </interactivity:Interaction.Behaviors> </Image> </Border>
总结
到这里我们就把 UWP Community Toolkit 中的 Animations 的种类和简单的代码调用讲解完成了,希望这些扩展对大家开发 UWP 应用有所帮助,如果大家有更好用的动画类,也欢迎大家给 UWPCommunityToolkit 做 PR,贡献自己的代码,欢迎大家多多交流!
而在后面,我会针对每种 Animation 做详细的代码分析和讲解,谢谢大家支持!
最后,再跟大家安利一下 UWPCommunityToolkit 的官方微博:https://weibo.com/u/6506046490, 大家可以通过微博关注最新动态。
衷心感谢 UWPCommunityToolkit 的作者们杰出的工作,Thank you so much, UWPCommunityToolkit authors!!!