Improved internal AnimationBuilder architecture

This commit is contained in:
Sergio Pedri 2020-12-21 17:46:06 +01:00
Родитель 9105cf0313
Коммит 1d3de3c1e5
8 изменённых файлов: 125 добавлений и 122 удалений

Просмотреть файл

@ -15,6 +15,8 @@ using Windows.UI.Xaml;
using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation; using Windows.UI.Xaml.Media.Animation;
#nullable enable
namespace Microsoft.Toolkit.Uwp.UI.Animations namespace Microsoft.Toolkit.Uwp.UI.Animations
{ {
/// <inheritdoc cref="AnimationBuilder"/> /// <inheritdoc cref="AnimationBuilder"/>
@ -35,13 +37,15 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
where T : unmanaged where T : unmanaged
{ {
/// <inheritdoc/> /// <inheritdoc/>
public CompositionAnimation GetAnimation(Visual visual) public CompositionAnimation GetAnimation(CompositionObject targetHint, out CompositionObject? target)
{ {
CompositionEasingFunction easingFunction = visual.Compositor.CreateCubicBezierEasingFunction(EasingType, EasingMode); CompositionEasingFunction easingFunction = targetHint.Compositor.CreateCubicBezierEasingFunction(EasingType, EasingMode);
target = null;
if (typeof(T) == typeof(bool)) if (typeof(T) == typeof(bool))
{ {
return visual.Compositor.CreateBooleanKeyFrameAnimation( return targetHint.Compositor.CreateBooleanKeyFrameAnimation(
Property, Property,
GetToAs<bool>(), GetToAs<bool>(),
GetFromAs<bool>(), GetFromAs<bool>(),
@ -50,7 +54,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
} }
else if (typeof(T) == typeof(float)) else if (typeof(T) == typeof(float))
{ {
return visual.Compositor.CreateScalarKeyFrameAnimation( return targetHint.Compositor.CreateScalarKeyFrameAnimation(
Property, Property,
GetToAs<float>(), GetToAs<float>(),
GetFromAs<float>(), GetFromAs<float>(),
@ -60,17 +64,17 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
} }
else if (typeof(T) == typeof(double)) else if (typeof(T) == typeof(double))
{ {
return visual.Compositor.CreateScalarKeyFrameAnimation( return targetHint.Compositor.CreateScalarKeyFrameAnimation(
Property, Property,
(float)GetToAs<double>(), (float)GetToAs<double>(),
(float)GetFromAs<double>(), (float?)GetFromAs<double>(),
Delay, Delay,
Duration, Duration,
easingFunction); easingFunction);
} }
else if (typeof(T) == typeof(Vector2)) else if (typeof(T) == typeof(Vector2))
{ {
return visual.Compositor.CreateVector2KeyFrameAnimation( return targetHint.Compositor.CreateVector2KeyFrameAnimation(
Property, Property,
GetToAs<Vector2>(), GetToAs<Vector2>(),
GetFromAs<Vector2>(), GetFromAs<Vector2>(),
@ -80,7 +84,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
} }
else if (typeof(T) == typeof(Vector3)) else if (typeof(T) == typeof(Vector3))
{ {
return visual.Compositor.CreateVector3KeyFrameAnimation( return targetHint.Compositor.CreateVector3KeyFrameAnimation(
Property, Property,
GetToAs<Vector3>(), GetToAs<Vector3>(),
GetFromAs<Vector3>(), GetFromAs<Vector3>(),
@ -90,7 +94,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
} }
else if (typeof(T) == typeof(Vector4)) else if (typeof(T) == typeof(Vector4))
{ {
return visual.Compositor.CreateVector4KeyFrameAnimation( return targetHint.Compositor.CreateVector4KeyFrameAnimation(
Property, Property,
GetToAs<Vector4>(), GetToAs<Vector4>(),
GetFromAs<Vector4>(), GetFromAs<Vector4>(),
@ -100,7 +104,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
} }
else if (typeof(T) == typeof(Color)) else if (typeof(T) == typeof(Color))
{ {
return visual.Compositor.CreateColorKeyFrameAnimation( return targetHint.Compositor.CreateColorKeyFrameAnimation(
Property, Property,
GetToAs<Color>(), GetToAs<Color>(),
GetFromAs<Color>(), GetFromAs<Color>(),
@ -110,7 +114,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
} }
else if (typeof(T) == typeof(Quaternion)) else if (typeof(T) == typeof(Quaternion))
{ {
return visual.Compositor.CreateQuaternionKeyFrameAnimation( return targetHint.Compositor.CreateQuaternionKeyFrameAnimation(
Property, Property,
GetToAs<Quaternion>(), GetToAs<Quaternion>(),
GetFromAs<Quaternion>(), GetFromAs<Quaternion>(),
@ -125,13 +129,13 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
} }
/// <inheritdoc/> /// <inheritdoc/>
public Timeline GetAnimation(UIElement element) public Timeline GetAnimation(DependencyObject targetHint)
{ {
EasingFunctionBase easingFunction = EasingType.ToEasingFunction(EasingMode); EasingFunctionBase? easingFunction = EasingType.ToEasingFunction(EasingMode);
if (typeof(T) == typeof(float)) if (typeof(T) == typeof(float))
{ {
return element.CreateDoubleAnimation( return targetHint.CreateDoubleAnimation(
Property, Property,
GetToAs<float>(), GetToAs<float>(),
GetFromAs<float>(), GetFromAs<float>(),
@ -142,7 +146,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
} }
else if (typeof(T) == typeof(double)) else if (typeof(T) == typeof(double))
{ {
return element.CreateDoubleAnimation( return targetHint.CreateDoubleAnimation(
Property, Property,
GetToAs<double>(), GetToAs<double>(),
GetFromAs<double>(), GetFromAs<double>(),
@ -153,7 +157,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
} }
else if (typeof(T) == typeof(Point)) else if (typeof(T) == typeof(Point))
{ {
return element.CreatePointAnimation( return targetHint.CreatePointAnimation(
Property, Property,
GetToAs<Point>(), GetToAs<Point>(),
GetFromAs<Point>(), GetFromAs<Point>(),
@ -164,7 +168,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
} }
else if (typeof(T) == typeof(Color)) else if (typeof(T) == typeof(Color))
{ {
return element.CreateColorAnimation( return targetHint.CreateColorAnimation(
Property, Property,
GetToAs<Color>(), GetToAs<Color>(),
GetFromAs<Color>(), GetFromAs<Color>(),
@ -214,30 +218,6 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
} }
} }
/// <summary>
/// A model representing a specified composition double animation for a target <see cref="CompositionObject"/>.
/// </summary>
private sealed record CompositionDoubleAnimation(
CompositionObject Target,
string Property,
float To,
float? From,
TimeSpan Delay,
TimeSpan Duration,
EasingType EasingType,
EasingMode EasingMode)
: ICompositionAnimation
{
/// <inheritdoc/>
public void StartAnimation()
{
CompositionEasingFunction easingFunction = Target.Compositor.CreateCubicBezierEasingFunction(EasingType, EasingMode);
ScalarKeyFrameAnimation animation = Target.Compositor.CreateScalarKeyFrameAnimation(Property, To, From, Delay, Duration, easingFunction);
Target.StartAnimation(Property, animation);
}
}
/// <summary> /// <summary>
/// A model representing a specified composition scalar animation factory targeting a clip. /// A model representing a specified composition scalar animation factory targeting a clip.
/// </summary> /// </summary>
@ -252,11 +232,40 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
: ICompositionAnimationFactory : ICompositionAnimationFactory
{ {
/// <inheritdoc/> /// <inheritdoc/>
public CompositionAnimation GetAnimation(Visual visual) public CompositionAnimation GetAnimation(CompositionObject targetHint, out CompositionObject? target)
{ {
Visual visual = (Visual)targetHint;
InsetClip clip = visual.Clip as InsetClip ?? (InsetClip)(visual.Clip = visual.Compositor.CreateInsetClip()); InsetClip clip = visual.Clip as InsetClip ?? (InsetClip)(visual.Clip = visual.Compositor.CreateInsetClip());
CompositionEasingFunction easingFunction = clip.Compositor.CreateCubicBezierEasingFunction(EasingType, EasingMode); CompositionEasingFunction easingFunction = clip.Compositor.CreateCubicBezierEasingFunction(EasingType, EasingMode);
ScalarKeyFrameAnimation animation = visual.Compositor.CreateScalarKeyFrameAnimation(Property, To, From, Delay, Duration, easingFunction); ScalarKeyFrameAnimation animation = clip.Compositor.CreateScalarKeyFrameAnimation(Property, To, From, Delay, Duration, easingFunction);
target = clip;
return animation;
}
}
/// <summary>
/// A model representing a specified composition double animation for a target <see cref="CompositionObject"/>.
/// </summary>
private sealed record CompositionDoubleAnimation(
CompositionObject Target,
string Property,
float To,
float? From,
TimeSpan Delay,
TimeSpan Duration,
EasingType EasingType,
EasingMode EasingMode)
: ICompositionAnimationFactory
{
/// <inheritdoc/>
public CompositionAnimation GetAnimation(CompositionObject targetHint, out CompositionObject? target)
{
CompositionEasingFunction easingFunction = Target.Compositor.CreateCubicBezierEasingFunction(EasingType, EasingMode);
ScalarKeyFrameAnimation animation = Target.Compositor.CreateScalarKeyFrameAnimation(Property, To, From, Delay, Duration, easingFunction);
target = Target;
return animation; return animation;
} }
@ -276,9 +285,9 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
: IXamlAnimationFactory : IXamlAnimationFactory
{ {
/// <inheritdoc/> /// <inheritdoc/>
public Timeline GetAnimation(UIElement element) public Timeline GetAnimation(DependencyObject targetHint)
{ {
CompositeTransform transform = element.GetTransform<CompositeTransform>(); CompositeTransform transform = ((UIElement)targetHint).GetTransform<CompositeTransform>();
return transform.CreateDoubleAnimation(Property, To, From, Duration, Delay, EasingType.ToEasingFunction(EasingMode)); return transform.CreateDoubleAnimation(Property, To, From, Duration, Delay, EasingType.ToEasingFunction(EasingMode));
} }
@ -292,9 +301,9 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
/// <summary> /// <summary>
/// Gets a <see cref="Timeline"/> instance representing the animation to start. /// Gets a <see cref="Timeline"/> instance representing the animation to start.
/// </summary> /// </summary>
/// <param name="element">The target <see cref="UIElement"/> instance to animate.</param> /// <param name="targetHint">The suggested target <see cref="DependencyObject"/> instance to animate.</param>
/// <returns>A <see cref="Timeline"/> instance with the specified animation.</returns> /// <returns>A <see cref="Timeline"/> instance with the specified animation.</returns>
Timeline GetAnimation(UIElement element); Timeline GetAnimation(DependencyObject targetHint);
} }
/// <summary> /// <summary>
@ -305,20 +314,15 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
/// <summary> /// <summary>
/// Gets a <see cref="CompositionAnimation"/> instance representing the animation to start. /// Gets a <see cref="CompositionAnimation"/> instance representing the animation to start.
/// </summary> /// </summary>
/// <param name="visual">The target <see cref="Visual"/> instance to animate.</param> /// <param name="targetHint">The suggested target <see cref="CompositionObject"/> instance to animate.</param>
/// <param name="target">An optional <see cref="CompositionObject"/> instance to animate instead of the suggested one.</param>
/// <returns>A <see cref="CompositionAnimation"/> instance with the specified animation.</returns> /// <returns>A <see cref="CompositionAnimation"/> instance with the specified animation.</returns>
CompositionAnimation GetAnimation(Visual visual); /// <remarks>
} /// The separate <paramref name="target"/> parameter is needed because unlike with XAML animations, composition animations
/// can't store the target instance internally, and need to be started on the target object directly. This means that custom
/// <summary> /// animation factories that want to target an external object need to return that object separately to inform the callers.
/// An interface for custom external composition animations. /// </remarks>
/// </summary> CompositionAnimation GetAnimation(CompositionObject targetHint, out CompositionObject? target);
internal interface ICompositionAnimation
{
/// <summary>
/// Starts a <see cref="CompositionAnimation"/> with some embedded parameters.
/// </summary>
void StartAnimation();
} }
} }
} }

Просмотреть файл

@ -14,11 +14,6 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
/// </summary> /// </summary>
public sealed partial class AnimationBuilder public sealed partial class AnimationBuilder
{ {
/// <summary>
/// The list of <see cref="ICompositionAnimation"/> instances representing animations to run.
/// </summary>
private readonly List<ICompositionAnimation> compositionAnimations = new();
/// <summary> /// <summary>
/// The list of <see cref="ICompositionAnimationFactory"/> instances representing factories for composition animations to run. /// The list of <see cref="ICompositionAnimationFactory"/> instances representing factories for composition animations to run.
/// </summary> /// </summary>

Просмотреть файл

@ -82,7 +82,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
easingType, easingType,
easingMode); easingMode);
this.compositionAnimations.Add(animation); this.compositionAnimationFactories.Add(animation);
return this; return this;
} }
@ -93,27 +93,25 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
/// <param name="element">The target <see cref="UIElement"/> to animate.</param> /// <param name="element">The target <see cref="UIElement"/> to animate.</param>
public void Start(UIElement element) public void Start(UIElement element)
{ {
if (this.compositionAnimations.Count > 0)
{
foreach (var animation in this.compositionAnimations)
{
animation.StartAnimation();
}
}
if (this.compositionAnimationFactories.Count > 0) if (this.compositionAnimationFactories.Count > 0)
{ {
ElementCompositionPreview.SetIsTranslationEnabled(element, true); ElementCompositionPreview.SetIsTranslationEnabled(element, true);
Visual visual = ElementCompositionPreview.GetElementVisual(element); Visual visual = ElementCompositionPreview.GetElementVisual(element);
CompositionAnimationGroup group = visual.Compositor.CreateAnimationGroup();
foreach (var factory in this.compositionAnimationFactories) foreach (var factory in this.compositionAnimationFactories)
{ {
group.Add(factory.GetAnimation(visual)); var animation = factory.GetAnimation(visual, out var target);
}
visual.StartAnimationGroup(group); if (target is null)
{
visual.StartAnimation(animation.Target, animation);
}
else
{
target.StartAnimation(animation.Target, animation);
}
}
} }
if (this.xamlAnimationFactories.Count > 0) if (this.xamlAnimationFactories.Count > 0)
@ -140,30 +138,29 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
compositionTask = Task.CompletedTask, compositionTask = Task.CompletedTask,
xamlTask = Task.CompletedTask; xamlTask = Task.CompletedTask;
if (this.compositionAnimationFactories.Count > 0 || if (this.compositionAnimationFactories.Count > 0)
this.compositionAnimations.Count > 0)
{ {
ElementCompositionPreview.SetIsTranslationEnabled(element, true);
Visual visual = ElementCompositionPreview.GetElementVisual(element); Visual visual = ElementCompositionPreview.GetElementVisual(element);
CompositionScopedBatch batch = visual.Compositor.CreateScopedBatch(CompositionBatchTypes.Animation); CompositionScopedBatch batch = visual.Compositor.CreateScopedBatch(CompositionBatchTypes.Animation);
TaskCompletionSource<object?> taskCompletionSource = new(); TaskCompletionSource<object?> taskCompletionSource = new();
batch.Completed += (_, _) => taskCompletionSource.SetResult(null); batch.Completed += (_, _) => taskCompletionSource.SetResult(null);
foreach (var animation in this.compositionAnimations)
{
animation.StartAnimation();
}
ElementCompositionPreview.SetIsTranslationEnabled(element, true);
CompositionAnimationGroup group = visual.Compositor.CreateAnimationGroup();
foreach (var factory in this.compositionAnimationFactories) foreach (var factory in this.compositionAnimationFactories)
{ {
group.Add(factory.GetAnimation(visual)); var animation = factory.GetAnimation(visual, out var target);
}
visual.StartAnimationGroup(group); if (target is null)
{
visual.StartAnimation(animation.Target, animation);
}
else
{
target.StartAnimation(animation.Target, animation);
}
}
batch.End(); batch.End();

Просмотреть файл

@ -10,6 +10,8 @@ using Microsoft.Toolkit.Uwp.UI.Animations.Extensions;
using Windows.UI; using Windows.UI;
using Windows.UI.Composition; using Windows.UI.Composition;
#nullable enable
namespace Microsoft.Toolkit.Uwp.UI.Animations namespace Microsoft.Toolkit.Uwp.UI.Animations
{ {
/// <inheritdoc cref="NormalizedKeyFrameAnimationBuilder{T}"/> /// <inheritdoc cref="NormalizedKeyFrameAnimationBuilder{T}"/>
@ -19,14 +21,14 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
/// Gets a <see cref="CompositionAnimation"/> instance representing the animation to start. /// Gets a <see cref="CompositionAnimation"/> instance representing the animation to start.
/// </summary> /// </summary>
/// <typeparam name="TKeyFrame">The type of keyframes being used to define the animation.</typeparam> /// <typeparam name="TKeyFrame">The type of keyframes being used to define the animation.</typeparam>
/// <param name="visual">The target <see cref="Visual"/> instance to animate.</param> /// <param name="target">The target <see cref="CompositionObject"/> instance to animate.</param>
/// <param name="property">The target property to animate.</param> /// <param name="property">The target property to animate.</param>
/// <param name="delay">The optional initial delay for the animation.</param> /// <param name="delay">The optional initial delay for the animation.</param>
/// <param name="duration">The animation duration.</param> /// <param name="duration">The animation duration.</param>
/// <param name="keyFrames">The list of keyframes to use to build the animation.</param> /// <param name="keyFrames">The list of keyframes to use to build the animation.</param>
/// <returns>A <see cref="CompositionAnimation"/> instance with the specified animation.</returns> /// <returns>A <see cref="CompositionAnimation"/> instance with the specified animation.</returns>
public static CompositionAnimation GetAnimation<TKeyFrame>( public static CompositionAnimation GetAnimation<TKeyFrame>(
Visual visual, CompositionObject target,
string property, string property,
TimeSpan? delay, TimeSpan? delay,
TimeSpan duration, TimeSpan duration,
@ -37,7 +39,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
if (typeof(T) == typeof(bool)) if (typeof(T) == typeof(bool))
{ {
BooleanKeyFrameAnimation boolAnimation = visual.Compositor.CreateBooleanKeyFrameAnimation(); BooleanKeyFrameAnimation boolAnimation = target.Compositor.CreateBooleanKeyFrameAnimation();
foreach (var keyFrame in keyFrames) foreach (var keyFrame in keyFrames)
{ {
@ -50,98 +52,98 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
} }
else if (typeof(T) == typeof(float)) else if (typeof(T) == typeof(float))
{ {
ScalarKeyFrameAnimation scalarAnimation = visual.Compositor.CreateScalarKeyFrameAnimation(); ScalarKeyFrameAnimation scalarAnimation = target.Compositor.CreateScalarKeyFrameAnimation();
foreach (var keyFrame in keyFrames) foreach (var keyFrame in keyFrames)
{ {
scalarAnimation.InsertKeyFrame( scalarAnimation.InsertKeyFrame(
(float)keyFrame.GetNormalizedProgress(duration), (float)keyFrame.GetNormalizedProgress(duration),
keyFrame.GetValueAs<float>(), keyFrame.GetValueAs<float>(),
visual.Compositor.CreateCubicBezierEasingFunction(keyFrame.EasingType, keyFrame.EasingMode)); target.Compositor.CreateCubicBezierEasingFunction(keyFrame.EasingType, keyFrame.EasingMode));
} }
animation = scalarAnimation; animation = scalarAnimation;
} }
else if (typeof(T) == typeof(double)) else if (typeof(T) == typeof(double))
{ {
ScalarKeyFrameAnimation scalarAnimation = visual.Compositor.CreateScalarKeyFrameAnimation(); ScalarKeyFrameAnimation scalarAnimation = target.Compositor.CreateScalarKeyFrameAnimation();
foreach (var keyFrame in keyFrames) foreach (var keyFrame in keyFrames)
{ {
scalarAnimation.InsertKeyFrame( scalarAnimation.InsertKeyFrame(
(float)keyFrame.GetNormalizedProgress(duration), (float)keyFrame.GetNormalizedProgress(duration),
(float)keyFrame.GetValueAs<double>(), (float)keyFrame.GetValueAs<double>(),
visual.Compositor.CreateCubicBezierEasingFunction(keyFrame.EasingType, keyFrame.EasingMode)); target.Compositor.CreateCubicBezierEasingFunction(keyFrame.EasingType, keyFrame.EasingMode));
} }
animation = scalarAnimation; animation = scalarAnimation;
} }
else if (typeof(T) == typeof(Vector2)) else if (typeof(T) == typeof(Vector2))
{ {
Vector2KeyFrameAnimation vector2Animation = visual.Compositor.CreateVector2KeyFrameAnimation(); Vector2KeyFrameAnimation vector2Animation = target.Compositor.CreateVector2KeyFrameAnimation();
foreach (var keyFrame in keyFrames) foreach (var keyFrame in keyFrames)
{ {
vector2Animation.InsertKeyFrame( vector2Animation.InsertKeyFrame(
(float)keyFrame.GetNormalizedProgress(duration), (float)keyFrame.GetNormalizedProgress(duration),
keyFrame.GetValueAs<Vector2>(), keyFrame.GetValueAs<Vector2>(),
visual.Compositor.CreateCubicBezierEasingFunction(keyFrame.EasingType, keyFrame.EasingMode)); target.Compositor.CreateCubicBezierEasingFunction(keyFrame.EasingType, keyFrame.EasingMode));
} }
animation = vector2Animation; animation = vector2Animation;
} }
else if (typeof(T) == typeof(Vector3)) else if (typeof(T) == typeof(Vector3))
{ {
Vector3KeyFrameAnimation vector3Animation = visual.Compositor.CreateVector3KeyFrameAnimation(); Vector3KeyFrameAnimation vector3Animation = target.Compositor.CreateVector3KeyFrameAnimation();
foreach (var keyFrame in keyFrames) foreach (var keyFrame in keyFrames)
{ {
vector3Animation.InsertKeyFrame( vector3Animation.InsertKeyFrame(
(float)keyFrame.GetNormalizedProgress(duration), (float)keyFrame.GetNormalizedProgress(duration),
keyFrame.GetValueAs<Vector3>(), keyFrame.GetValueAs<Vector3>(),
visual.Compositor.CreateCubicBezierEasingFunction(keyFrame.EasingType, keyFrame.EasingMode)); target.Compositor.CreateCubicBezierEasingFunction(keyFrame.EasingType, keyFrame.EasingMode));
} }
animation = vector3Animation; animation = vector3Animation;
} }
else if (typeof(T) == typeof(Vector4)) else if (typeof(T) == typeof(Vector4))
{ {
Vector4KeyFrameAnimation vector4Animation = visual.Compositor.CreateVector4KeyFrameAnimation(); Vector4KeyFrameAnimation vector4Animation = target.Compositor.CreateVector4KeyFrameAnimation();
foreach (var keyFrame in keyFrames) foreach (var keyFrame in keyFrames)
{ {
vector4Animation.InsertKeyFrame( vector4Animation.InsertKeyFrame(
(float)keyFrame.GetNormalizedProgress(duration), (float)keyFrame.GetNormalizedProgress(duration),
keyFrame.GetValueAs<Vector4>(), keyFrame.GetValueAs<Vector4>(),
visual.Compositor.CreateCubicBezierEasingFunction(keyFrame.EasingType, keyFrame.EasingMode)); target.Compositor.CreateCubicBezierEasingFunction(keyFrame.EasingType, keyFrame.EasingMode));
} }
animation = vector4Animation; animation = vector4Animation;
} }
else if (typeof(T) == typeof(Color)) else if (typeof(T) == typeof(Color))
{ {
ColorKeyFrameAnimation colorAnimation = visual.Compositor.CreateColorKeyFrameAnimation(); ColorKeyFrameAnimation colorAnimation = target.Compositor.CreateColorKeyFrameAnimation();
foreach (var keyFrame in keyFrames) foreach (var keyFrame in keyFrames)
{ {
colorAnimation.InsertKeyFrame( colorAnimation.InsertKeyFrame(
(float)keyFrame.GetNormalizedProgress(duration), (float)keyFrame.GetNormalizedProgress(duration),
keyFrame.GetValueAs<Color>(), keyFrame.GetValueAs<Color>(),
visual.Compositor.CreateCubicBezierEasingFunction(keyFrame.EasingType, keyFrame.EasingMode)); target.Compositor.CreateCubicBezierEasingFunction(keyFrame.EasingType, keyFrame.EasingMode));
} }
animation = colorAnimation; animation = colorAnimation;
} }
else if (typeof(T) == typeof(Quaternion)) else if (typeof(T) == typeof(Quaternion))
{ {
QuaternionKeyFrameAnimation quaternionAnimation = visual.Compositor.CreateQuaternionKeyFrameAnimation(); QuaternionKeyFrameAnimation quaternionAnimation = target.Compositor.CreateQuaternionKeyFrameAnimation();
foreach (var keyFrame in keyFrames) foreach (var keyFrame in keyFrames)
{ {
quaternionAnimation.InsertKeyFrame( quaternionAnimation.InsertKeyFrame(
(float)keyFrame.GetNormalizedProgress(duration), (float)keyFrame.GetNormalizedProgress(duration),
keyFrame.GetValueAs<Quaternion>(), keyFrame.GetValueAs<Quaternion>(),
visual.Compositor.CreateCubicBezierEasingFunction(keyFrame.EasingType, keyFrame.EasingMode)); target.Compositor.CreateCubicBezierEasingFunction(keyFrame.EasingType, keyFrame.EasingMode));
} }
animation = quaternionAnimation; animation = quaternionAnimation;
@ -178,10 +180,12 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
} }
/// <inheritdoc/> /// <inheritdoc/>
public CompositionAnimation GetAnimation(Visual visual) public CompositionAnimation GetAnimation(CompositionObject targetHint, out CompositionObject? target)
{ {
target = null;
return GetAnimation( return GetAnimation(
visual, targetHint,
this.property, this.property,
this.delay, this.delay,
this.duration, this.duration,

Просмотреть файл

@ -27,10 +27,10 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
} }
/// <inheritdoc/> /// <inheritdoc/>
public Timeline GetAnimation(UIElement element) public Timeline GetAnimation(DependencyObject targetHint)
{ {
return TimedKeyFrameAnimationBuilder<T>.GetAnimation( return TimedKeyFrameAnimationBuilder<T>.GetAnimation(
element, targetHint,
this.property, this.property,
this.delay, this.delay,
this.duration, this.duration,

Просмотреть файл

@ -5,6 +5,8 @@
using System; using System;
using Windows.UI.Composition; using Windows.UI.Composition;
#nullable enable
namespace Microsoft.Toolkit.Uwp.UI.Animations namespace Microsoft.Toolkit.Uwp.UI.Animations
{ {
/// <inheritdoc cref="TimedKeyFrameAnimationBuilder{T}"/> /// <inheritdoc cref="TimedKeyFrameAnimationBuilder{T}"/>
@ -26,14 +28,16 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
} }
/// <inheritdoc/> /// <inheritdoc/>
public CompositionAnimation GetAnimation(Visual visual) public CompositionAnimation GetAnimation(CompositionObject targetHint, out CompositionObject? target)
{ {
target = null;
// We can retrieve the total duration from the last timed keyframe, and then set // We can retrieve the total duration from the last timed keyframe, and then set
// this as the target duration and use it to normalize the keyframe progresses. // this as the target duration and use it to normalize the keyframe progresses.
TimeSpan duration = this.keyFrames[this.keyFrames.Count - 1].GetTimedProgress(default); TimeSpan duration = this.keyFrames[this.keyFrames.Count - 1].GetTimedProgress(default);
return NormalizedKeyFrameAnimationBuilder<T>.GetAnimation( return NormalizedKeyFrameAnimationBuilder<T>.GetAnimation(
visual, targetHint,
this.property, this.property,
this.delay, this.delay,
duration, duration,

Просмотреть файл

@ -4,7 +4,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics;
using Microsoft.Toolkit.Diagnostics; using Microsoft.Toolkit.Diagnostics;
using Microsoft.Toolkit.Uwp.UI.Animations.Extensions; using Microsoft.Toolkit.Uwp.UI.Animations.Extensions;
using Windows.Foundation; using Windows.Foundation;
@ -22,14 +21,14 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
/// Gets a <see cref="Timeline"/> instance representing the animation to start. /// Gets a <see cref="Timeline"/> instance representing the animation to start.
/// </summary> /// </summary>
/// <typeparam name="TKeyFrame">The type of keyframes being used to define the animation.</typeparam> /// <typeparam name="TKeyFrame">The type of keyframes being used to define the animation.</typeparam>
/// <param name="element">The target <see cref="UIElement"/> instance to animate.</param> /// <param name="target">The target <see cref="DependencyObject"/> instance to animate.</param>
/// <param name="property">The target property to animate.</param> /// <param name="property">The target property to animate.</param>
/// <param name="delay">The optional initial delay for the animation.</param> /// <param name="delay">The optional initial delay for the animation.</param>
/// <param name="duration">The animation duration.</param> /// <param name="duration">The animation duration.</param>
/// <param name="keyFrames">The list of keyframes to use to build the animation.</param> /// <param name="keyFrames">The list of keyframes to use to build the animation.</param>
/// <returns>A <see cref="Timeline"/> instance with the specified animation.</returns> /// <returns>A <see cref="Timeline"/> instance with the specified animation.</returns>
public static Timeline GetAnimation<TKeyFrame>( public static Timeline GetAnimation<TKeyFrame>(
UIElement element, DependencyObject target,
string property, string property,
TimeSpan? delay, TimeSpan? delay,
TimeSpan duration, TimeSpan duration,
@ -109,7 +108,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
animation.BeginTime = delay; animation.BeginTime = delay;
Storyboard.SetTarget(animation, element); Storyboard.SetTarget(animation, target);
Storyboard.SetTargetProperty(animation, property); Storyboard.SetTargetProperty(animation, property);
return animation; return animation;
@ -130,10 +129,10 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
} }
/// <inheritdoc/> /// <inheritdoc/>
public Timeline GetAnimation(UIElement element) public Timeline GetAnimation(DependencyObject targetHint)
{ {
return GetAnimation( return GetAnimation(
element, targetHint,
this.property, this.property,
this.delay, this.delay,
default, default,

Просмотреть файл

@ -30,8 +30,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Media.Animations
return builder.DoubleAnimation( return builder.DoubleAnimation(
effect.Brush, effect.Brush,
$"{effect.Id}.{nameof(GaussianBlurEffect.BlurAmount)}", $"{effect.Id}.{nameof(GaussianBlurEffect.BlurAmount)}",
From,
To, To,
From,
Delay ?? delayHint, Delay ?? delayHint,
Duration ?? durationHint.GetValueOrDefault(), Duration ?? durationHint.GetValueOrDefault(),
EasingType ?? easingTypeHint ?? DefaultEasingType, EasingType ?? easingTypeHint ?? DefaultEasingType,