Skip to content

Commit 8647919

Browse files
Add initial basic animation support for Shadows
1 parent 0459a89 commit 8647919

File tree

7 files changed

+169
-1
lines changed

7 files changed

+169
-1
lines changed

Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,7 @@
632632
</Content>
633633
<Content Include="SamplePages\Shadows\AttachedShadowWin2DXaml.bind" />
634634
<Content Include="SamplePages\Shadows\AttachedShadowCompositionXaml.bind" />
635+
<Content Include="SamplePages\Animations\Shadows\AnimatedCardShadowXaml.bind" />
635636
<Content Include="SamplePages\KeyDownTriggerBehavior\KeyDownTriggerBehaviorXaml.bind" />
636637
</ItemGroup>
637638
<ItemGroup>

Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Animations/Effects/FadeBehaviorXaml.bind

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
xmlns:interactions="using:Microsoft.Xaml.Interactions.Core"
88
xmlns:ani="using:Microsoft.Toolkit.Uwp.UI.Animations"
99
xmlns:behaviors="using:Microsoft.Toolkit.Uwp.UI.Behaviors"
10-
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
1110
mc:Ignorable="d">
1211

1312
<Button Background="Gray" Width="200" Height="200" HorizontalAlignment="Center" VerticalAlignment="Center">
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<Page
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6+
xmlns:ui="using:Microsoft.Toolkit.Uwp.UI"
7+
xmlns:media="using:Microsoft.Toolkit.Uwp.UI.Media"
8+
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
9+
xmlns:interactions="using:Microsoft.Xaml.Interactions.Core"
10+
xmlns:ani="using:Microsoft.Toolkit.Uwp.UI.Animations"
11+
xmlns:behaviors="using:Microsoft.Toolkit.Uwp.UI.Behaviors"
12+
mc:Ignorable="d">
13+
14+
<Page.Resources>
15+
<media:AttachedCardShadow x:Key="CommonShadow" Offset="4" CornerRadius="0"/>
16+
</Page.Resources>
17+
18+
<Grid>
19+
<Image x:Name="ImageWithShadow"
20+
ui:Effects.Shadow="{StaticResource CommonShadow}"
21+
Height="100" Width="100"
22+
Source="ms-appx:///Assets/Photos/Owl.jpg">
23+
<interactivity:Interaction.Behaviors>
24+
<interactions:EventTriggerBehavior EventName="PointerEntered">
25+
<behaviors:StartAnimationAction Animation="{Binding ElementName=ShadowEnterAnimation}"/>
26+
</interactions:EventTriggerBehavior>
27+
<interactions:EventTriggerBehavior EventName="PointerExited">
28+
<behaviors:StartAnimationAction Animation="{Binding ElementName=ShadowExitAnimation}"/>
29+
</interactions:EventTriggerBehavior>
30+
</interactivity:Interaction.Behaviors>
31+
<ani:Explicit.Animations>
32+
<ani:AnimationSet x:Name="ShadowEnterAnimation">
33+
<ani:OffsetDropShadowAnimation From="4" To="12" Target="{Binding ElementName=ImageWithShadow}"/>
34+
</ani:AnimationSet>
35+
36+
<ani:AnimationSet x:Name="ShadowExitAnimation">
37+
<ani:OffsetDropShadowAnimation From="12" To="4" Target="{Binding ElementName=ImageWithShadow}"/>
38+
</ani:AnimationSet>
39+
</ani:Explicit.Animations>
40+
</Image>
41+
</Grid>
42+
</Page>

Microsoft.Toolkit.Uwp.SampleApp/SamplePages/XamlOnlyPage.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
<ani:SaturationEffectAnimation />
6868
<ani:AnimationScope />
6969
<ani:ExposureEffectAnimation />
70+
<ani:OffsetDropShadowAnimation />
7071
</ani:AnimationSet>
7172
</ani:Explicit.Animations>
7273
<media:UIElementExtensions.VisualFactory>

Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,15 @@
651651
"DisableXamlEditorRendering": true,
652652
"Icon": "/SamplePages/Connected Animations/ConnectedAnimations.png",
653653
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/animations/ConnectedAnimations.md"
654+
},
655+
{
656+
"Name": "Shadow Animations",
657+
"Subcategory": "Effect",
658+
"About": "Example of animating an Attached Shadow",
659+
"CodeUrl": "https://github.com/CommunityToolkit/WindowsCommunityToolkit/tree/main/Microsoft.Toolkit.Uwp.UI.Animations/Xaml/Shadows",
660+
"XamlCodeFile": "/SamplePages/Animations/Shadows/AnimatedCardShadowXaml.bind",
661+
"Icon": "/SamplePages/Shadows/DropShadowPanel.png",
662+
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/animations/ConnectedAnimations.md"
654663
}
655664
]
656665
},
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using Windows.UI.Composition;
7+
using Windows.UI.Xaml;
8+
using Windows.UI.Xaml.Media.Animation;
9+
using static Microsoft.Toolkit.Uwp.UI.Animations.AnimationExtensions;
10+
11+
#nullable enable
12+
13+
namespace Microsoft.Toolkit.Uwp.UI.Animations
14+
{
15+
/// <summary>
16+
/// A custom animation targeting a property on an <see cref="AttachedShadowBase"/> instance.
17+
/// </summary>
18+
/// <typeparam name="TShadow">The <see cref="FrameworkElement"/> containing the shadow to animate.</typeparam>
19+
/// <typeparam name="TValue">
20+
/// The type to use for the public <see cref="Animation{TValue,TKeyFrame}.To"/> and <see cref="Animation{TValue,TKeyFrame}.From"/>
21+
/// properties. This can differ from <typeparamref name="TKeyFrame"/> to facilitate XAML parsing.
22+
/// </typeparam>
23+
/// <typeparam name="TKeyFrame">The actual type of keyframe values in use.</typeparam>
24+
public abstract class ShadowAnimation<TShadow, TValue, TKeyFrame> : Animation<TValue, TKeyFrame>
25+
where TShadow : FrameworkElement
26+
where TKeyFrame : unmanaged
27+
{
28+
/// <summary>
29+
/// Gets or sets the linked <typeparamref name="TShadow"/> instance to animate.
30+
/// </summary>
31+
public TShadow? Target
32+
{
33+
get => (TShadow?)GetValue(TargetProperty);
34+
set => SetValue(TargetProperty, value);
35+
}
36+
37+
/// <summary>
38+
/// Identifies the <seealso cref="Target"/> dependency property.
39+
/// </summary>
40+
public static readonly DependencyProperty TargetProperty = DependencyProperty.Register(
41+
nameof(Target),
42+
typeof(TShadow),
43+
typeof(ShadowAnimation<TShadow, TValue, TKeyFrame>),
44+
new PropertyMetadata(null));
45+
46+
/// <inheritdoc/>
47+
public override AnimationBuilder AppendToBuilder(AnimationBuilder builder, TimeSpan? delayHint, TimeSpan? durationHint, EasingType? easingTypeHint, EasingMode? easingModeHint)
48+
{
49+
if (Target is not TShadow target)
50+
{
51+
static AnimationBuilder ThrowTargetNullException() => throw new ArgumentNullException("The target element is null, make sure to set the Target property");
52+
53+
return ThrowTargetNullException();
54+
}
55+
56+
var shadowBase = Effects.GetShadow(Target);
57+
if (shadowBase == null)
58+
{
59+
static AnimationBuilder ThrowArgumentNullException() => throw new ArgumentNullException("The target's shadow is null, make sure to set the Target property to an element with a Shadow");
60+
61+
return ThrowArgumentNullException();
62+
}
63+
64+
if (ExplicitTarget is not string explicitTarget)
65+
{
66+
static AnimationBuilder ThrowArgumentNullException()
67+
{
68+
throw new ArgumentNullException(
69+
"The target shadow cannot be animated at this time.");
70+
}
71+
72+
return ThrowArgumentNullException();
73+
}
74+
75+
var shadow = shadowBase.GetElementContext(Target).Shadow;
76+
77+
NormalizedKeyFrameAnimationBuilder<TKeyFrame>.Composition keyFrameBuilder = new(
78+
explicitTarget,
79+
Delay ?? delayHint ?? DefaultDelay,
80+
Duration ?? durationHint ?? DefaultDuration,
81+
Repeat,
82+
DelayBehavior);
83+
84+
AppendToBuilder(keyFrameBuilder, easingTypeHint, easingModeHint);
85+
86+
CompositionAnimation animation = keyFrameBuilder.GetAnimation(shadow, out _);
87+
88+
return builder.ExternalAnimation(shadow, animation);
89+
}
90+
}
91+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Numerics;
6+
using Windows.UI.Composition;
7+
using Windows.UI.Xaml;
8+
9+
namespace Microsoft.Toolkit.Uwp.UI.Animations
10+
{
11+
/// <summary>
12+
/// An offset animation working on the composition layer.
13+
/// </summary>
14+
public sealed class OffsetDropShadowAnimation : ShadowAnimation<FrameworkElement, string, Vector3>
15+
{
16+
/// <inheritdoc/>
17+
protected override string ExplicitTarget => nameof(DropShadow.Offset);
18+
19+
/// <inheritdoc/>
20+
protected override (Vector3?, Vector3?) GetParsedValues()
21+
{
22+
return (To?.ToVector3(), From?.ToVector3());
23+
}
24+
}
25+
}

0 commit comments

Comments
 (0)