diff --git a/UICompositionAnimations/Animations/Abstract/AnimationBuilderBase.cs b/UICompositionAnimations/Animations/Abstract/AnimationBuilderBase.cs index 2c49970..967e546 100644 --- a/UICompositionAnimations/Animations/Abstract/AnimationBuilderBase.cs +++ b/UICompositionAnimations/Animations/Abstract/AnimationBuilderBase.cs @@ -167,6 +167,37 @@ internal abstract class AnimationBuilderBase : IAnimationBuilder [MustUseReturnValue, NotNull] protected abstract IAnimationBuilder OnClip(Side side, double? from, double to, Easing ease); + /// + public IAnimationBuilder Size(Axis axis, double to, Easing ease = Easing.Linear) => OnSize(axis, null, to, ease); + + /// + public IAnimationBuilder Size(Axis axis, double from, double to, Easing ease = Easing.Linear) => OnSize(axis, from, to, ease); + + /// + /// Schedules a size animation on a single axis + /// + /// The target axis to animate + /// The optional starting value + /// The target value + /// The easing function to use for the size animation + [MustUseReturnValue, NotNull] + protected abstract IAnimationBuilder OnSize(Axis axis, double? from, double to, Easing ease); + + /// + public IAnimationBuilder Size(Vector2 to, Easing ease = Easing.Linear) => OnSize(null, to, ease); + + /// + public IAnimationBuilder Size(Vector2 from, Vector2 to, Easing ease = Easing.Linear) => OnSize(from, to, ease); + + /// + /// Schedules a 2D size animation + /// + /// The optional starting position + /// The target position + /// The easing function to use for the size animation + [MustUseReturnValue, NotNull] + protected abstract IAnimationBuilder OnSize(Vector2? from, Vector2 to, Easing ease = Easing.Linear); + #endregion /// diff --git a/UICompositionAnimations/Animations/CompositionAnimationBuilder.cs b/UICompositionAnimations/Animations/CompositionAnimationBuilder.cs index 375ab5c..dad2c4c 100644 --- a/UICompositionAnimations/Animations/CompositionAnimationBuilder.cs +++ b/UICompositionAnimations/Animations/CompositionAnimationBuilder.cs @@ -29,92 +29,19 @@ public CompositionAnimationBuilder([NotNull] UIElement target) : base(target) } /// - protected override IAnimationBuilder OnOpacity(double? from, double to, Easing ease) - { - AnimationFactories.Add(duration => - { - TargetVisual.StopAnimation(nameof(Visual.Opacity)); - CompositionEasingFunction easingFunction = TargetVisual.GetEasingFunction(ease); - ScalarKeyFrameAnimation animation = TargetVisual.Compositor.CreateScalarKeyFrameAnimation((float?)from, (float)to, duration, null, easingFunction); - TargetVisual.StartAnimation(nameof(Visual.Opacity), animation); - }); - - return this; - } + protected override IAnimationBuilder OnOpacity(double? from, double to, Easing ease) => OnScalarAnimation(nameof(Visual.Opacity), from, to, ease); /// - protected override IAnimationBuilder OnTranslation(Axis axis, double? from, double to, Easing ease) - { - AnimationFactories.Add(duration => - { - // Stop the animation and get the easing function - string property = $"Translation.{axis}"; - TargetVisual.StopAnimation(property); - CompositionEasingFunction easingFunction = TargetVisual.GetEasingFunction(ease); - - // Create and return the animation - ScalarKeyFrameAnimation animation = TargetVisual.Compositor.CreateScalarKeyFrameAnimation((float?)from, (float)to, duration, null, easingFunction); - TargetVisual.StartAnimation(property, animation); - }); - - return this; - } + protected override IAnimationBuilder OnTranslation(Axis axis, double? from, double to, Easing ease) => OnScalarAnimation($"Translation.{axis}", from, to, ease); /// - protected override IAnimationBuilder OnTranslation(Vector2? from, Vector2 to, Easing ease = Easing.Linear) - { - AnimationFactories.Add(duration => - { - // Stop the animation and get the easing function - TargetVisual.StopAnimation("Translation"); - CompositionEasingFunction easingFunction = TargetVisual.GetEasingFunction(ease); - - // Create and return the animation - Vector3? from3 = from == null ? default : new Vector3(from.Value, 0); - Vector3 to3 = new Vector3(to, 0); - Vector3KeyFrameAnimation animation = TargetVisual.Compositor.CreateVector3KeyFrameAnimation(from3, to3, duration, null, easingFunction); - TargetVisual.StartAnimation("Translation", animation); - }); - - return this; - } + protected override IAnimationBuilder OnTranslation(Vector2? from, Vector2 to, Easing ease = Easing.Linear) => OnVector3Animation("Translation", from, to, ease); /// - protected override IAnimationBuilder OnOffset(Axis axis, double? from, double to, Easing ease) - { - AnimationFactories.Add(duration => - { - // Stop the animation and get the easing function - string property = $"{nameof(Visual.Offset)}.{axis}"; - TargetVisual.StopAnimation(property); - CompositionEasingFunction easingFunction = TargetVisual.GetEasingFunction(ease); - - // Create and return the animation - ScalarKeyFrameAnimation animation = TargetVisual.Compositor.CreateScalarKeyFrameAnimation((float?)from, (float)to, duration, null, easingFunction); - TargetVisual.StartAnimation(property, animation); - }); - - return this; - } + protected override IAnimationBuilder OnOffset(Axis axis, double? from, double to, Easing ease) => OnScalarAnimation($"{nameof(Visual.Offset)}.{axis}", from, to, ease); /// - protected override IAnimationBuilder OnOffset(Vector2? from, Vector2 to, Easing ease = Easing.Linear) - { - AnimationFactories.Add(duration => - { - // Stop the animation and get the easing function - TargetVisual.StopAnimation(nameof(Visual.Offset)); - CompositionEasingFunction easingFunction = TargetVisual.GetEasingFunction(ease); - - // Create and return the animation - Vector3? from3 = from == null ? default : new Vector3(from.Value, 0); - Vector3 to3 = new Vector3(to, 0); - Vector3KeyFrameAnimation animation = TargetVisual.Compositor.CreateVector3KeyFrameAnimation(from3, to3, duration, null, easingFunction); - TargetVisual.StartAnimation(nameof(Visual.Offset), animation); - }); - - return this; - } + protected override IAnimationBuilder OnOffset(Vector2? from, Vector2 to, Easing ease = Easing.Linear) => OnVector3Animation(nameof(Visual.Offset), from, to, ease); /// protected override IAnimationBuilder OnScale(double? from, double to, Easing ease) @@ -124,20 +51,9 @@ protected override IAnimationBuilder OnScale(double? from, double to, Easing eas element.GetVisual().CenterPoint = new Vector3((float)(element.ActualWidth / 2), (float)(element.ActualHeight / 2), 0); // Add the scale animation - AnimationFactories.Add(duration => - { - // Stop the animation and get the easing function - TargetVisual.StopAnimation(nameof(Visual.Scale)); - CompositionEasingFunction easingFunction = TargetVisual.GetEasingFunction(ease); - - // Create and return the animation - Vector3? from3 = from == null ? default : new Vector3((float)from.Value, (float)from.Value, 0); - Vector3 to3 = new Vector3((float)to, (float)to, 0); - Vector3KeyFrameAnimation animation = TargetVisual.Compositor.CreateVector3KeyFrameAnimation(from3, to3, duration, null, easingFunction); - TargetVisual.StartAnimation(nameof(Visual.Scale), animation); - }); - - return this; + Vector2? from2 = from == null ? default(Vector2?) : new Vector2((float)from.Value, (float)from.Value); + Vector2 to2 = new Vector2((float)to, (float)to); + return OnVector3Animation(nameof(Visual.Scale), from2, to2, ease); } /// @@ -148,15 +64,7 @@ protected override IAnimationBuilder OnRotate(double? from, double to, Easing ea element.GetVisual().CenterPoint = new Vector3((float)(element.ActualWidth / 2), (float)(element.ActualHeight / 2), 0); // Add the rotation animation - AnimationFactories.Add(duration => - { - TargetVisual.StopAnimation(nameof(Visual.RotationAngleInDegrees)); - CompositionEasingFunction easingFunction = TargetVisual.GetEasingFunction(ease); - ScalarKeyFrameAnimation animation = TargetVisual.Compositor.CreateScalarKeyFrameAnimation((float?)from, (float)to, duration, null, easingFunction); - TargetVisual.StartAnimation(nameof(Visual.RotationAngleInDegrees), animation); - }); - - return this; + return OnScalarAnimation(nameof(Visual.RotationAngleInDegrees), from, to, ease); } /// @@ -186,6 +94,62 @@ protected override IAnimationBuilder OnClip(Side side, double? from, double to, return this; } + /// + protected override IAnimationBuilder OnSize(Axis axis, double? from, double to, Easing ease) => OnScalarAnimation($"{nameof(Visual.Size)}.{axis}", from, to, ease); + + /// + protected override IAnimationBuilder OnSize(Vector2? from, Vector2 to, Easing ease = Easing.Linear) => OnVector3Animation(nameof(Visual.Size), from, to, ease); + + /// + /// Schedules a scalar animation targeting the current item + /// + /// The target property to animate + /// The optional starting value for the scalar animation + /// The target value for the scalar animation + /// The easing function to use for the scalar animation + [MustUseReturnValue, NotNull] + private IAnimationBuilder OnScalarAnimation(string property, double? from, double to, Easing ease) + { + AnimationFactories.Add(duration => + { + // Stop the animation and get the easing function + TargetVisual.StopAnimation(property); + CompositionEasingFunction easingFunction = TargetVisual.GetEasingFunction(ease); + + // Create and return the animation + ScalarKeyFrameAnimation animation = TargetVisual.Compositor.CreateScalarKeyFrameAnimation((float?)from, (float)to, duration, null, easingFunction); + TargetVisual.StartAnimation(property, animation); + }); + + return this; + } + + /// + /// Schedules a vector animation targeting the current item + /// + /// The target property to animate + /// The optional starting value for the vector animation + /// The target value for the vector animation + /// The easing function to use for the vector animation + [MustUseReturnValue, NotNull] + private IAnimationBuilder OnVector3Animation(string property, Vector2? from, Vector2 to, Easing ease) + { + AnimationFactories.Add(duration => + { + // Stop the animation and get the easing function + TargetVisual.StopAnimation(property); + CompositionEasingFunction easingFunction = TargetVisual.GetEasingFunction(ease); + + // Create and return the animation + Vector3? from3 = from == null ? default(Vector3?) : new Vector3(from.Value, 0); + Vector3 to3 = new Vector3(to, 0); + Vector3KeyFrameAnimation animation = TargetVisual.Compositor.CreateVector3KeyFrameAnimation(from3, to3, duration, null, easingFunction); + TargetVisual.StartAnimation(property, animation); + }); + + return this; + } + /// /// Creates and starts the pending animations /// diff --git a/UICompositionAnimations/Animations/Interfaces/IAnimationBuilder.cs b/UICompositionAnimations/Animations/Interfaces/IAnimationBuilder.cs index 7bf99d4..202cc33 100644 --- a/UICompositionAnimations/Animations/Interfaces/IAnimationBuilder.cs +++ b/UICompositionAnimations/Animations/Interfaces/IAnimationBuilder.cs @@ -154,6 +154,42 @@ public interface IAnimationBuilder [MustUseReturnValue, NotNull] IAnimationBuilder Clip(Side side, double from, double to, Easing ease = Easing.Linear); + /// + /// Schedules a size animation + /// + /// The size axis to animate + /// The target size value to animate to + /// The easing function to use for the size animation + [MustUseReturnValue, NotNull] + IAnimationBuilder Size(Axis axis, double to, Easing ease = Easing.Linear); + + /// + /// Schedules a size animation + /// + /// The size axis to animate + /// The initial size value to animate from + /// The target size value to animate to + /// The easing function to use for the size animation + [MustUseReturnValue, NotNull] + IAnimationBuilder Size(Axis axis, double from, double to, Easing ease = Easing.Linear); + + /// + /// Schedules a size animation + /// + /// The target size position to animate to + /// The easing function to use for the size animation + [MustUseReturnValue, NotNull] + IAnimationBuilder Size(Vector2 to, Easing ease = Easing.Linear); + + /// + /// Schedules a size animation + /// + /// The initial size position to animate from + /// The target size position to animate to + /// The easing function to use for the size animation + [MustUseReturnValue, NotNull] + IAnimationBuilder Size(Vector2 from, Vector2 to, Easing ease = Easing.Linear); + /// /// Sets the duration of the animation /// diff --git a/UICompositionAnimations/Animations/XamlAnimationBuilder.cs b/UICompositionAnimations/Animations/XamlAnimationBuilder.cs index f219ff1..1bb9bc9 100644 --- a/UICompositionAnimations/Animations/XamlAnimationBuilder.cs +++ b/UICompositionAnimations/Animations/XamlAnimationBuilder.cs @@ -77,7 +77,37 @@ protected override IAnimationBuilder OnRotate(double? from, double to, Easing ea } /// - protected override IAnimationBuilder OnClip(Side side, double? @from, double to, Easing ease) => throw new NotSupportedException("Can't animate the clip property from XAML"); + protected override IAnimationBuilder OnClip(Side side, double? from, double to, Easing ease) => throw new NotSupportedException("Can't animate the clip property from XAML"); + + /// + protected override IAnimationBuilder OnSize(Axis axis, double? from, double to, Easing ease) + { + if (!(TargetElement is FrameworkElement element)) throw new InvalidOperationException("Can't animate the size of an item that's not a framework element"); + AnimationFactories.Add(duration => + { + switch (axis) + { + case Axis.X: return TargetElement.CreateDoubleAnimation(nameof(FrameworkElement.Width), double.IsNaN(element.Width) ? element.ActualWidth : from, to, duration, ease, true); + case Axis.Y: return TargetElement.CreateDoubleAnimation(nameof(FrameworkElement.Height), double.IsNaN(element.Height) ? element.ActualHeight : from, to, duration, ease, true); + default: throw new ArgumentException($"Invalid axis: {axis}", nameof(axis)); + } + }); + + return this; + } + + /// + protected override IAnimationBuilder OnSize(Vector2? from, Vector2 to, Easing ease = Easing.Linear) + { + if (!(TargetElement is FrameworkElement element)) throw new InvalidOperationException("Can't animate the size of an item that's not a framework element"); + double? + fromX = double.IsNaN(element.Width) ? (double?)element.ActualWidth : from?.X, + fromY = double.IsNaN(element.Height) ? (double?)element.ActualHeight : from?.Y; + AnimationFactories.Add(duration => TargetTransform.CreateDoubleAnimation(nameof(FrameworkElement.Width), fromX, to.X, duration, ease, true)); + AnimationFactories.Add(duration => TargetTransform.CreateDoubleAnimation(nameof(FrameworkElement.Height), fromY, to.Y, duration, ease, true)); + + return this; + } /// /// Gets the represented by the current instance diff --git a/UICompositionAnimations/Properties/AssemblyInfo.cs b/UICompositionAnimations/Properties/AssemblyInfo.cs index d9aa125..6d6795c 100644 --- a/UICompositionAnimations/Properties/AssemblyInfo.cs +++ b/UICompositionAnimations/Properties/AssemblyInfo.cs @@ -23,8 +23,8 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("4.0.1.0")] -[assembly: AssemblyFileVersion("4.0.1.0")] -[assembly: AssemblyInformationalVersion("4.0.1")] +[assembly: AssemblyVersion("4.0.2.0")] +[assembly: AssemblyFileVersion("4.0.2.0")] +[assembly: AssemblyInformationalVersion("4.0.2")] [assembly: ComVisible(false)] diff --git a/UICompositionAnimations/UICompositionAnimations.nuspec b/UICompositionAnimations/UICompositionAnimations.nuspec index a93e4c6..f513e02 100644 --- a/UICompositionAnimations/UICompositionAnimations.nuspec +++ b/UICompositionAnimations/UICompositionAnimations.nuspec @@ -2,7 +2,7 @@ UICompositionAnimations - 4.0.1 + 4.0.2 UICompositionAnimations A wrapper UWP PCL to work with Windows.UI.Composition and XAML animations, and Win2D effects Sergio Pedri @@ -10,7 +10,7 @@ https://github.com/Sergio0694/UICompositionAnimations GPL-3.0-only false - New overloads added, minor bug fixes + New size animation APIs, minor fixes Copyright © 2019 uwp composition animations xaml csharp windows winrt universal app ui win2d graphics