Browse Source

*Added initial implementation of new Transitions

*Added default easing classes
*Added easing type converter
pull/1461/head
Jumar Macato 8 years ago
parent
commit
7becd1ea92
  1. 20
      samples/RenderTest/Pages/AnimationsPage.xaml.cs
  2. 16
      samples/RenderTest/Pages/ClippingPage.xaml.cs
  3. 88
      src/Avalonia.Animation/Animatable.cs
  4. 60
      src/Avalonia.Animation/AnimationExtensions.cs
  5. 100
      src/Avalonia.Animation/Animation`1.cs
  6. 21
      src/Avalonia.Animation/Easing/BackEaseIn.cs
  7. 32
      src/Avalonia.Animation/Easing/BackEaseInOut.cs
  8. 21
      src/Avalonia.Animation/Easing/BackEaseOut.cs
  9. 20
      src/Avalonia.Animation/Easing/BounceEaseIn.cs
  10. 27
      src/Avalonia.Animation/Easing/BounceEaseInOut.cs
  11. 19
      src/Avalonia.Animation/Easing/BounceEaseOut.cs
  12. 23
      src/Avalonia.Animation/Easing/CircularEaseIn.cs
  13. 29
      src/Avalonia.Animation/Easing/CircularEaseInOut.cs
  14. 22
      src/Avalonia.Animation/Easing/CircularEaseOut.cs
  15. 18
      src/Avalonia.Animation/Easing/CubicEaseIn.cs
  16. 29
      src/Avalonia.Animation/Easing/CubicEaseInOut.cs
  17. 19
      src/Avalonia.Animation/Easing/CubicEaseOut.cs
  18. 58
      src/Avalonia.Animation/Easing/Easing.cs
  19. 22
      src/Avalonia.Animation/Easing/ElasticEaseIn.cs
  20. 30
      src/Avalonia.Animation/Easing/ElasticEaseInOut.cs
  21. 23
      src/Avalonia.Animation/Easing/ElasticEaseOut.cs
  22. 21
      src/Avalonia.Animation/Easing/ExponentialEaseIn.cs
  23. 30
      src/Avalonia.Animation/Easing/ExponentialEaseInOut.cs
  24. 21
      src/Avalonia.Animation/Easing/ExponentialEaseOut.cs
  25. 18
      src/Avalonia.Animation/Easing/LinearEasing.cs
  26. 18
      src/Avalonia.Animation/Easing/QuadraticEaseIn.cs
  27. 28
      src/Avalonia.Animation/Easing/QuadraticEaseInOut.cs
  28. 19
      src/Avalonia.Animation/Easing/QuadraticEaseOut.cs
  29. 20
      src/Avalonia.Animation/Easing/QuarticEaseIn.cs
  30. 29
      src/Avalonia.Animation/Easing/QuarticEaseInOut.cs
  31. 20
      src/Avalonia.Animation/Easing/QuarticEaseOut.cs
  32. 18
      src/Avalonia.Animation/Easing/QuinticEaseIn.cs
  33. 28
      src/Avalonia.Animation/Easing/QuinticEaseInOut.cs
  34. 19
      src/Avalonia.Animation/Easing/QuinticEaseOut.cs
  35. 20
      src/Avalonia.Animation/Easing/SineEaseIn.cs
  36. 20
      src/Avalonia.Animation/Easing/SineEaseInOut.cs
  37. 21
      src/Avalonia.Animation/Easing/SineEaseOut.cs
  38. 39
      src/Avalonia.Animation/Helpers/BounceEaseHelper.cs
  39. 18
      src/Avalonia.Animation/Helpers/DoubleHelper.cs
  40. 18
      src/Avalonia.Animation/Helpers/EasingConstants.cs
  41. 11
      src/Avalonia.Animation/IEasing.cs
  42. 24
      src/Avalonia.Animation/IEasing`1.cs
  43. 41
      src/Avalonia.Animation/LinearDoubleEasing.cs
  44. 35
      src/Avalonia.Animation/LinearEasing.cs
  45. 2
      src/Avalonia.Animation/Properties/AssemblyInfo.cs
  46. 50
      src/Avalonia.Animation/PropertyTransition.cs
  47. 57
      src/Avalonia.Animation/Timing.cs
  48. 32
      src/Avalonia.Animation/Transitions/DoubleTransition.cs
  49. 59
      src/Avalonia.Animation/Transitions/Transition.cs
  50. 8
      src/Avalonia.Animation/Transitions/Transitions.cs
  51. 12
      src/Avalonia.Controls/ProgressBar.cs
  52. 30
      src/Avalonia.Visuals/Animation/CrossFade.cs
  53. 30
      src/Avalonia.Visuals/Animation/PageSlide.cs
  54. 1
      src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
  55. 24
      src/Markup/Avalonia.Markup.Xaml/Converters/EasingTypeConverter.cs
  56. 2
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaDefaultTypeConverters.cs

20
samples/RenderTest/Pages/AnimationsPage.xaml.cs

@ -56,17 +56,17 @@ namespace RenderTest.Pages
RenderTransform = new ScaleTransform(),
};
var start = Animate.Stopwatch.Elapsed;
var index = i % (Count / 2);
var degrees = Animate.Timer
.Select(x => (x - start).TotalSeconds)
.Where(x => (x % Count) >= index && (x % Count) < index + 1)
.Select(x => (x % 1) / 1);
//var start = Animate.Stopwatch.Elapsed;
//var index = i % (Count / 2);
//var degrees = Animate.Timer
// .Select(x => (x - start).TotalSeconds)
// .Where(x => (x % Count) >= index && (x % Count) < index + 1)
// .Select(x => (x % 1) / 1);
element.RenderTransform.Bind(
ScaleTransform.ScaleXProperty,
degrees,
BindingPriority.Animation);
//element.RenderTransform.Bind(
// ScaleTransform.ScaleXProperty,
// degrees,
// BindingPriority.Animation);
ellipse.PointerEnter += Ellipse_PointerEnter;
ellipse.PointerLeave += Ellipse_PointerLeave;

16
samples/RenderTest/Pages/ClippingPage.xaml.cs

@ -27,14 +27,14 @@ namespace RenderTest.Pages
private void CreateAnimations()
{
var clipped = this.FindControl<Border>("clipChild");
var degrees = Animate.Timer.Select(x => x.TotalMilliseconds / 5);
clipped.RenderTransform = new RotateTransform();
clipped.RenderTransform.Bind(RotateTransform.AngleProperty, degrees, BindingPriority.Animation);
clipped.Bind(
Border.BackgroundProperty,
clipped.GetObservable(Control.IsPointerOverProperty)
.Select(x => x ? Brushes.Crimson : AvaloniaProperty.UnsetValue));
//var clipped = this.FindControl<Border>("clipChild");
//var degrees = Animate.Timer.Select(x => x.TotalMilliseconds / 5);
//clipped.RenderTransform = new RotateTransform();
//clipped.RenderTransform.Bind(RotateTransform.AngleProperty, degrees, BindingPriority.Animation);
//clipped.Bind(
// Border.BackgroundProperty,
// clipped.GetObservable(Control.IsPointerOverProperty)
// .Select(x => x ? Brushes.Crimson : AvaloniaProperty.UnsetValue));
}
private void WireUpCheckbox()

88
src/Avalonia.Animation/Animatable.cs

@ -3,6 +3,8 @@
using System.Linq;
using Avalonia.Data;
using System;
using System.Reactive.Linq;
namespace Avalonia.Animation
{
@ -11,46 +13,102 @@ namespace Avalonia.Animation
/// </summary>
public class Animatable : AvaloniaObject
{
/// <summary>
/// The property transitions for the control.
/// </summary>
private PropertyTransitions _propertyTransitions;
private Transitions _transitions;
/// <summary>
/// Gets or sets the property transitions for the control.
/// </summary>
/// <value>
/// The property transitions for the control.
/// </value>
public PropertyTransitions PropertyTransitions
public Transitions Transitions
{
get
{
return _propertyTransitions ?? (_propertyTransitions = new PropertyTransitions());
return _transitions ?? (_transitions = new Transitions());
}
set
{
_propertyTransitions = value;
SetAndRaise(TransitionsProperty, ref _transitions, value);
}
}
/// <summary>
/// Reacts to a change in a <see cref="AvaloniaProperty"/> value in order to animate the
/// change if a <see cref="PropertyTransition"/> is set for the property..
/// Gets or sets the property transitions for the control.
/// </summary>
public static readonly DirectProperty<Animatable, Transitions> TransitionsProperty =
AvaloniaProperty.RegisterDirect<Animatable, Transitions>(nameof(Transitions), o => o.Transitions);
/// <summary>
/// Reacts to a change in a <see cref="AvaloniaProperty"/> value in
/// order to animate the change if a <see cref="ITransition"/>
/// is set for the property.
/// </summary>
/// <param name="e">The event args.</param>
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
{
if (e.Priority != BindingPriority.Animation && _propertyTransitions != null)
if (e.Priority != BindingPriority.Animation && Transitions != null)
{
var match = _propertyTransitions.FirstOrDefault(x => x.Property == e.Property);
var match = Transitions.FirstOrDefault(x => x.Property == e.Property);
if (match != null)
{
Animate.Property(this, e.Property, e.OldValue, e.NewValue, match.Easing, match.Duration);
// //BindAnimateProperty(this, e.Property, e.OldValue, e.NewValue, match.Easing, match.Duration);
}
}
}
/// <summary>
/// Animates a <see cref="AvaloniaProperty"/>.
/// </summary>
/// <param name="target">The target object.</param>
/// <param name="property">The target property.</param>
/// <param name="start">The value of the property at the start of the animation.</param>
/// <param name="finish">The value of the property at the end of the animation.</param>
/// <param name="easing">The easing function to use.</param>
/// <param name="duration">The duration of the animation.</param>
/// <returns>An <see cref="Animation"/> that can be used to track or stop the animation.</returns>
//public static Animation BindAnimateProperty(
// IAvaloniaObject target,
// AvaloniaProperty property,
// object start,
// object finish,
// IEasing easing,
// TimeSpan duration)
//{
// var k = start.GetType();
// if (k == typeof(double))
// {
// var o = Timing.GetTimer(duration).Select(progress => easing.Ease(progress, start, finish));
// return new Animation(o, target.Bind(property, o, BindingPriority.Animation));
// }
// else
// return null;
//}
///// <summary>
///// Animates a <see cref="AvaloniaProperty"/>.
///// </summary>
///// <typeparam name="T">The property type.</typeparam>
///// <param name="target">The target object.</param>
///// <param name="property">The target property.</param>
///// <param name="start">The value of the property at the start of the animation.</param>
///// <param name="finish">The value of the property at the end of the animation.</param>
///// <param name="easing">The easing function to use.</param>
///// <param name="duration">The duration of the animation.</param>
///// <returns>An <see cref="Animation"/> that can be used to track or stop the animation.</returns>
//public static Animation<T> Property<T>(
// IAvaloniaObject target,
// AvaloniaProperty<T> property,
// T start,
// T finish,
// IEasing<T> easing,
// TimeSpan duration)
//{
// var o = Timing.GetTimer(duration).Select(progress => easing.Ease(progress, start, finish));
// return new Animation<T>(o, target.Bind(property, o, BindingPriority.Animation));
//}
}
}

60
src/Avalonia.Animation/AnimationExtensions.cs

@ -10,36 +10,36 @@ namespace Avalonia.Animation
/// </summary>
public static class AnimationExtensions
{
/// <summary>
/// Returns a new <see cref="PropertyTransition"/> for the specified
/// <see cref="AvaloniaProperty"/> using linear easing.
/// </summary>
/// <typeparam name="T">The type of the <see cref="AvaloniaProperty"/>.</typeparam>
/// <param name="property">The property to animate.</param>
/// <param name="milliseconds">The animation duration in milliseconds.</param>
/// <returns>
/// A <see cref="PropertyTransition"/> that can be added to the
/// <see cref="Animatable.PropertyTransitions"/> collection.
/// </returns>
public static PropertyTransition Transition<T>(this AvaloniaProperty<T> property, int milliseconds)
{
return Transition(property, TimeSpan.FromMilliseconds(milliseconds));
}
///// <summary>
///// Returns a new <see cref="Avalonia.Animation.Transition"/> for the specified
///// <see cref="AvaloniaProperty"/> using linear easing.
///// </summary>
///// <typeparam name="T">The type of the <see cref="AvaloniaProperty"/>.</typeparam>
///// <param name="property">The property to animate.</param>
///// <param name="milliseconds">The animation duration in milliseconds.</param>
///// <returns>
///// A <see cref="Avalonia.Animation.Transition"/> that can be added to the
///// <see cref="Animatable.Transitions"/> collection.
///// </returns>
//public static Transition Transition<T>(this AvaloniaProperty<T> property, int milliseconds)
//{
// return Transition(property, TimeSpan.FromMilliseconds(milliseconds));
//}
/// <summary>
/// Returns a new <see cref="PropertyTransition"/> for the specified
/// <see cref="AvaloniaProperty"/> using linear easing.
/// </summary>
/// <typeparam name="T">The type of the <see cref="AvaloniaProperty"/>.</typeparam>
/// <param name="property">The property to animate.</param>
/// <param name="duration">The animation duration.</param>
/// <returns>
/// A <see cref="PropertyTransition"/> that can be added to the
/// <see cref="Animatable.PropertyTransitions"/> collection.
/// </returns>
public static PropertyTransition Transition<T>(this AvaloniaProperty<T> property, TimeSpan duration)
{
return new PropertyTransition(property, duration, LinearEasing.For<T>());
}
///// <summary>
///// Returns a new <see cref="Avalonia.Animation.Transition"/> for the specified
///// <see cref="AvaloniaProperty"/> using linear easing.
///// </summary>
///// <typeparam name="T">The type of the <see cref="AvaloniaProperty"/>.</typeparam>
///// <param name="property">The property to animate.</param>
///// <param name="duration">The animation duration.</param>
///// <returns>
///// A <see cref="Avalonia.Animation.Transition"/> that can be added to the
///// <see cref="Animatable.Transitions"/> collection.
///// </returns>
//public static Transition Transition<T>(this AvaloniaProperty<T> property, TimeSpan duration)
//{
// return new Transition(property, duration, LinearEasing.For<T>());
//}
}
}

100
src/Avalonia.Animation/Animation`1.cs

@ -1,56 +1,56 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
//// Copyright (c) The Avalonia Project. All rights reserved.
//// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
//using System;
namespace Avalonia.Animation
{
/// <summary>
/// Tracks the progress of an animation.
/// </summary>
/// <typeparam name="T">The type of the value being animated./</typeparam>
public class Animation<T> : IObservable<T>, IDisposable
{
/// <summary>
/// The animation being tracked.
/// </summary>
private readonly IObservable<T> _inner;
//namespace Avalonia.Animation
//{
// /// <summary>
// /// Tracks the progress of an animation.
// /// </summary>
// /// <typeparam name="T">The type of the value being animated./</typeparam>
// public class Animation<T> : IObservable<T>, IDisposable
// {
// /// <summary>
// /// The animation being tracked.
// /// </summary>
// private readonly IObservable<T> _inner;
/// <summary>
/// The disposable used to cancel the animation.
/// </summary>
private readonly IDisposable _subscription;
// /// <summary>
// /// The disposable used to cancel the animation.
// /// </summary>
// private readonly IDisposable _subscription;
/// <summary>
/// Initializes a new instance of the <see cref="Animation{T}"/> class.
/// </summary>
/// <param name="inner">The animation observable being tracked.</param>
/// <param name="subscription">A disposable used to cancel the animation.</param>
public Animation(IObservable<T> inner, IDisposable subscription)
{
_inner = inner;
_subscription = subscription;
}
// /// <summary>
// /// Initializes a new instance of the <see cref="Animation{T}"/> class.
// /// </summary>
// /// <param name="inner">The animation observable being tracked.</param>
// /// <param name="subscription">A disposable used to cancel the animation.</param>
// public Animation(IObservable<T> inner, IDisposable subscription)
// {
// _inner = inner;
// _subscription = subscription;
// }
/// <summary>
/// Cancels the animation.
/// </summary>
public void Dispose()
{
_subscription.Dispose();
}
// /// <summary>
// /// Cancels the animation.
// /// </summary>
// public void Dispose()
// {
// _subscription.Dispose();
// }
/// <summary>
/// Notifies the provider that an observer is to receive notifications.
/// </summary>
/// <param name="observer">The observer.</param>
/// <returns>
/// A reference to an interface that allows observers to stop receiving notifications
/// before the provider has finished sending them.
/// </returns>
public IDisposable Subscribe(IObserver<T> observer)
{
return _inner.Subscribe(observer);
}
}
}
// /// <summary>
// /// Notifies the provider that an observer is to receive notifications.
// /// </summary>
// /// <param name="observer">The observer.</param>
// /// <returns>
// /// A reference to an interface that allows observers to stop receiving notifications
// /// before the provider has finished sending them.
// /// </returns>
// public IDisposable Subscribe(IObserver<T> observer)
// {
// return _inner.Subscribe(observer);
// }
// }
//}

21
src/Avalonia.Animation/Easing/BackEaseIn.cs

@ -0,0 +1,21 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Animation
{
/// <summary>
/// Eases in a <see cref="double"/> value
/// using a overshooting cubic function.
/// </summary>
public class BackEaseIn : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double p = progress;
return p * p * p - p * Math.Sin(p * Math.PI);
}
}
}

32
src/Avalonia.Animation/Easing/BackEaseInOut.cs

@ -0,0 +1,32 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Animation.Easings
{
/// <summary>
/// Eases a <see cref="double"/> value
/// using a piecewise overshooting cubic function.
/// </summary>
public class BackEaseInOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double p = progress;
if (p < 0.5d)
{
double f = 2d * p;
return 0.5d * (f * f * f - f * Math.Sin(f * Math.PI));
}
else
{
double f = (1d - (2d * p - 1d));
return 0.5d * (1d - (f * f * f - f * Math.Sin(f * Math.PI))) + 0.5d;
}
}
}
}

21
src/Avalonia.Animation/Easing/BackEaseOut.cs

@ -0,0 +1,21 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Animation
{
/// <summary>
/// Eases out a <see cref="double"/> value
/// using a overshooting cubic function.
/// </summary>
public class BackEaseOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double p = 1d - progress;
return 1 - (p * p * p - p * Math.Sin(p * Math.PI));
}
}
}

20
src/Avalonia.Animation/Easing/BounceEaseIn.cs

@ -0,0 +1,20 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Animation
{
/// <summary>
/// Eases in a <see cref="double"/> value
/// using a simulated bounce function.
/// </summary>
public class BounceEaseIn : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
return 1 - BounceEaseHelper.Bounce(1 - progress);
}
}
}

27
src/Avalonia.Animation/Easing/BounceEaseInOut.cs

@ -0,0 +1,27 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Animation
{
/// <summary>
/// Eases a <see cref="double"/> value
/// using a piecewise simulated bounce function.
/// </summary>
public class BounceEaseInOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double p = progress;
if (p < 0.5d)
{
return 0.5f * (1 - BounceEaseHelper.Bounce(1 - (p * 2)));
}
else
{
return 0.5f * BounceEaseHelper.Bounce(p * 2 - 1) + 0.5f;
}
}
}
}

19
src/Avalonia.Animation/Easing/BounceEaseOut.cs

@ -0,0 +1,19 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Animation
{
/// <summary>
/// Eases out a <see cref="double"/> value
/// using a simulated bounce function.
/// </summary>
public class BounceEaseOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
return BounceEaseHelper.Bounce(progress);
}
}
}

23
src/Avalonia.Animation/Easing/CircularEaseIn.cs

@ -0,0 +1,23 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Animation
{
/// <summary>
/// Eases in a <see cref="double"/> value
/// using the shifted fourth quadrant of
/// the unit circle.
/// </summary>
public class CircularEaseIn : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double p = progress;
return 1d - Math.Sqrt(1d - (p * p));
}
}
}

29
src/Avalonia.Animation/Easing/CircularEaseInOut.cs

@ -0,0 +1,29 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Animation
{
/// <summary>
/// Eases a <see cref="double"/> value
/// using a piecewise unit circle function.
/// </summary>
public class CircularEaseInOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double p = progress;
if (p < 0.5d)
{
return 0.5d * (1d - Math.Sqrt(1d - 4d * (p * p)));
}
else
{
return 0.5d * (Math.Sqrt(-((2d * p) - 3d) * ((2d * p) - 1d)) + 1d);
}
}
}
}

22
src/Avalonia.Animation/Easing/CircularEaseOut.cs

@ -0,0 +1,22 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Animation
{
/// <summary>
/// Eases out a <see cref="double"/> value
/// using the shifted second quadrant of
/// the unit circle.
/// </summary>
public class CircularEaseOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double p = progress;
return Math.Sqrt((2d - p) * p);
}
}
}

18
src/Avalonia.Animation/Easing/CubicEaseIn.cs

@ -0,0 +1,18 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Animation
{
/// <summary>
/// Eases in a <see cref="double"/> value
/// using a cubic equation.
/// </summary>
public class CubicEaseIn : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
return progress * progress * progress;
}
}
}

29
src/Avalonia.Animation/Easing/CubicEaseInOut.cs

@ -0,0 +1,29 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Animation
{
/// <summary>
/// Eases a <see cref="double"/> value
/// using a piece-wise cubic equation.
/// </summary>
public class CubicEaseInOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double p = progress;
if (progress < 0.5d)
{
return 4d * p * p * p;
}
else
{
double f = ((2d * p) - 2d);
return 0.5d * f * f * f + 1d;
}
}
}
}

19
src/Avalonia.Animation/Easing/CubicEaseOut.cs

@ -0,0 +1,19 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Animation
{
/// <summary>
/// Eases out a <see cref="double"/> value
/// using a cubic equation.
/// </summary>
public class CubicEaseOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double f = (progress - 1d);
return f * f * f + 1d;
}
}
}

58
src/Avalonia.Animation/Easing/Easing.cs

@ -0,0 +1,58 @@
using Avalonia.Collections;
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Linq;
using System.ComponentModel;
namespace Avalonia.Animation
{
/// <summary>
/// Base class for all Easing classes.
/// </summary>
public abstract class Easing : IEasing
{
/// <inheritdoc/>
public abstract double Ease(double progress);
static Dictionary<string, Type> _easingTypes;
static readonly Type s_thisType = typeof(Easing);
/// <summary>
/// Parses a Easing type string.
/// </summary>
/// <param name="e">The Easing type string.</param>
/// <returns>Returns the instance of the parsed type.</returns>
public static Easing Parse(string e)
{
// TODO: There should be a better way to
// find all the subclasses than this method...
if (_easingTypes == null)
{
_easingTypes = new Dictionary<string, Type>();
var derivedTypes = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(p => p.GetTypes())
.Where(p => p.Namespace == s_thisType.Namespace)
.Where(p => p.IsSubclassOf(s_thisType))
.Select(p=>p).ToList();
foreach (var easingType in derivedTypes)
_easingTypes.Add(easingType.Name, easingType);
}
if (_easingTypes.ContainsKey(e))
{
var type = _easingTypes[e];
return (Easing)Activator.CreateInstance(type);
}
else
{
throw new FormatException($"Easing \"{e}\" was not found in {s_thisType.Namespace} namespace.");
}
}
}
}

22
src/Avalonia.Animation/Easing/ElasticEaseIn.cs

@ -0,0 +1,22 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Animation
{
/// <summary>
/// Eases in a <see cref="double"/> value
/// using a damped sine function.
/// </summary>
public class ElasticEaseIn : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double p = progress;
return Math.Sin(13d * EasingConstants.HALFPI * p) * Math.Pow(2d, 10d * (p - 1));
}
}
}

30
src/Avalonia.Animation/Easing/ElasticEaseInOut.cs

@ -0,0 +1,30 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Animation
{
/// <summary>
/// Eases a <see cref="double"/> value
/// using a piecewise damped sine function.
/// </summary>
public class ElasticEaseInOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double p = progress;
if (p < 0.5d)
{
return 0.5d * Math.Sin(13d * EasingConstants.HALFPI * (2d * p)) * Math.Pow(2d, 10d * ((2d * p) - 1d));
}
else
{
return 0.5d * (Math.Sin(-13d * EasingConstants.HALFPI * ((2d * p - 1d) + 1d)) * Math.Pow(2d, -10d * (2d * p - 1d)) + 2d);
}
}
}
}

23
src/Avalonia.Animation/Easing/ElasticEaseOut.cs

@ -0,0 +1,23 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Animation
{
/// <summary>
/// Eases out a <see cref="double"/> value
/// using a damped sine function.
/// </summary>
public class ElasticEaseOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double p = progress;
return Math.Sin(-13d * EasingConstants.HALFPI * (p + 1)) * Math.Pow(2d, -10d * p) + 1d;
}
}
}

21
src/Avalonia.Animation/Easing/ExponentialEaseIn.cs

@ -0,0 +1,21 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Animation
{
/// <summary>
/// Eases in a <see cref="double"/> value
/// using a exponential function.
/// </summary>
public class ExponentialEaseIn : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double p = progress;
return (p == 0.0d) ? p : Math.Pow(2d, 10d * (p - 1d));
}
}
}

30
src/Avalonia.Animation/Easing/ExponentialEaseInOut.cs

@ -0,0 +1,30 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Animation
{
/// <summary>
/// Eases a <see cref="double"/> value
/// using a piecewise exponential function.
/// </summary>
public class ExponentialEaseInOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double p = progress;
if (p < 0.5d)
{
return 0.5d * Math.Pow(2d, (20d * p) - 10d);
}
else
{
return -0.5d * Math.Pow(2d, (-20d * p) + 10d) + 1d;
}
}
}
}

21
src/Avalonia.Animation/Easing/ExponentialEaseOut.cs

@ -0,0 +1,21 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Animation
{
/// <summary>
/// Eases out a <see cref="double"/> value
/// using a exponential function.
/// </summary>
public class ExponentialEaseOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double p = progress;
return (p == 1.0d) ? p : 1d - Math.Pow(2d, -10d * p);
}
}
}

18
src/Avalonia.Animation/Easing/LinearEasing.cs

@ -0,0 +1,18 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Animation
{
/// <summary>
/// Linearly eases a <see cref="double"/> value.
/// </summary>
public class LinearEasing : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
return progress;
}
}
}

18
src/Avalonia.Animation/Easing/QuadraticEaseIn.cs

@ -0,0 +1,18 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Animation
{
/// <summary>
/// Eases in a <see cref="double"/> value
/// using a quadratic function.
/// </summary>
public class QuadraticEaseIn : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
return progress * progress;
}
}
}

28
src/Avalonia.Animation/Easing/QuadraticEaseInOut.cs

@ -0,0 +1,28 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Animation
{
/// <summary>
/// Eases a <see cref="double"/> value
/// using a piece-wise quadratic function.
/// </summary>
public class QuadraticEaseInOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double p = progress;
if (progress < 0.5d)
{
return 2d * p * p;
}
else
{
return (-2d * p * p) + (4d * p) - 1d;
}
}
}
}

19
src/Avalonia.Animation/Easing/QuadraticEaseOut.cs

@ -0,0 +1,19 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Animation
{
/// <summary>
/// Eases out a <see cref="double"/> value
/// using a quadratic function.
/// </summary>
public class QuadraticEaseOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
return -(progress * (progress - 2d));
}
}
}

20
src/Avalonia.Animation/Easing/QuarticEaseIn.cs

@ -0,0 +1,20 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Animation
{
/// <summary>
/// Eases in a <see cref="double"/> value
/// using a quartic equation.
/// </summary>
public class QuarticEaseIn : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
return progress * progress * progress * progress;
}
}
}

29
src/Avalonia.Animation/Easing/QuarticEaseInOut.cs

@ -0,0 +1,29 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Animation
{
/// <summary>
/// Eases a <see cref="double"/> value
/// using a piece-wise quartic equation.
/// </summary>
public class QuarticEaseInOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double p = progress;
if (p < 0.5d)
{
return 8d * p * p * p * p;
}
else
{
double f = (p - 1d);
return -8d * f * f * f * f + 1d;
}
}
}
}

20
src/Avalonia.Animation/Easing/QuarticEaseOut.cs

@ -0,0 +1,20 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Animation
{
/// <summary>
/// Eases out a <see cref="double"/> value
/// using a quartic equation.
/// </summary>
public class QuarticEaseOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double f = (progress - 1d);
return f * f * f * (1d - progress) + 1d;
}
}
}

18
src/Avalonia.Animation/Easing/QuinticEaseIn.cs

@ -0,0 +1,18 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Animation
{
/// <summary>
/// Eases in a <see cref="double"/> value
/// using a quartic equation.
/// </summary>
public class QuinticEaseIn : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
return progress * progress * progress * progress * progress;
}
}
}

28
src/Avalonia.Animation/Easing/QuinticEaseInOut.cs

@ -0,0 +1,28 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Animation
{
/// <summary>
/// Eases a <see cref="double"/> value
/// using a piece-wise quartic equation.
/// </summary>
public class QuinticEaseInOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double p = progress;
if (progress < 0.5d)
{
return 16d * p * p * p * p * p;
}
else
{
double f = ((2d * p) - 2d);
return 0.5d * f * f * f * f * f + 1d;
}
}
}
}

19
src/Avalonia.Animation/Easing/QuinticEaseOut.cs

@ -0,0 +1,19 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Animation
{
/// <summary>
/// Eases out a <see cref="double"/> value
/// using a quartic equation.
/// </summary>
public class QuinticEaseOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
double f = (progress - 1d);
return f * f * f * f * f + 1d;
}
}
}

20
src/Avalonia.Animation/Easing/SineEaseIn.cs

@ -0,0 +1,20 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Animation
{
/// <summary>
/// Eases in a <see cref="double"/> value
/// using the quarter-wave of sine function.
/// </summary>
public class SineEaseIn : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
return Math.Sin((progress - 1) * EasingConstants.HALFPI) + 1;
}
}
}

20
src/Avalonia.Animation/Easing/SineEaseInOut.cs

@ -0,0 +1,20 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Animation
{
/// <summary>
/// Eases a <see cref="double"/> value
/// using a half sine wave function.
/// </summary>
public class SineEaseInOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
return 0.5d * (1d - Math.Cos(progress * Math.PI));
}
}
}

21
src/Avalonia.Animation/Easing/SineEaseOut.cs

@ -0,0 +1,21 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Animation
{
/// <summary>
/// Eases out a <see cref="double"/> value
/// using the quarter-wave of sine function
/// with shifted phase.
/// </summary>
public class SineEaseOut : Easing
{
/// <inheritdoc/>
public override double Ease(double progress)
{
return Math.Sin(progress * EasingConstants.HALFPI);
}
}
}

39
src/Avalonia.Animation/Helpers/BounceEaseHelper.cs

@ -0,0 +1,39 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Animation
{
/// <summary>
/// Helper static class for BounceEase classes.
/// </summary>
internal static class BounceEaseHelper
{
/// <summary>
/// Returns the consequent <see cref="double"/> value of
/// a simulated bounce function.
/// </summary>
/// <param name="progress">The amount of progress from 0 to 1.</param>
/// <returns>The result of the easing function</returns>
internal static double Bounce(double progress)
{
double p = progress;
if (p < 4d / 11.0d)
{
return (121d * p * p) / 16.0d;
}
else if (p < 8d / 11.0d)
{
return (363d / 40.0d * p * p) - (99d / 10.0d * p) + 17d / 5.0d;
}
else if (p < 9d / 10.0d)
{
return (4356d / 361.0d * p * p) - (35442d / 1805.0d * p) + 16061d / 1805.0d;
}
else
{
return (54d / 5.0d * p * p) - (513d / 25.0d * p) + 268d / 25.0d;
}
}
}
}

18
src/Avalonia.Animation/Helpers/DoubleHelper.cs

@ -0,0 +1,18 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Text;
namespace Avalonia.Animation.Helpers
{
internal static class DoubleHelper
{
internal static bool AboutEqual(double x, double y)
{
double epsilon = Math.Max(Math.Abs(x), Math.Abs(y)) * 1E-15;
return Math.Abs(x - y) <= epsilon;
}
}
}

18
src/Avalonia.Animation/Helpers/EasingConstants.cs

@ -0,0 +1,18 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Animation
{
/// <summary>
/// Helper static class for easing mathematical constants.
/// </summary>
internal static class EasingConstants
{
/// <summary>
/// Half of <see cref="Math.PI"/>
/// </summary>
internal static double HALFPI = Math.PI / 2d;
}
}

11
src/Avalonia.Animation/IEasing.cs

@ -4,20 +4,13 @@
namespace Avalonia.Animation
{
/// <summary>
/// Defines the interface for easing functions.
/// Defines the interface for easing classes.
/// </summary>
public interface IEasing
{
/// <summary>
/// Returns the value of the transition for the specified progress.
/// </summary>
/// <param name="progress">The progress of the transition, from 0 to 1.</param>
/// <param name="start">The start value of the transition.</param>
/// <param name="finish">The end value of the transition.</param>
/// <returns>
/// A value between <paramref name="start"/> and <paramref name="finish"/> as determined
/// by <paramref name="progress"/>.
/// </returns>
object Ease(double progress, object start, object finish);
double Ease(double progress);
}
}

24
src/Avalonia.Animation/IEasing`1.cs

@ -1,24 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Animation
{
/// <summary>
/// Defines the interface for easing functions.
/// </summary>
/// <typeparam name="T">The type of the property being transitioned.</typeparam>
public interface IEasing<T> : IEasing
{
/// <summary>
/// Returns the value of the transition for the specified progress.
/// </summary>
/// <param name="progress">The progress of the transition, from 0 to 1.</param>
/// <param name="start">The start value of the transition.</param>
/// <param name="finish">The end value of the transition.</param>
/// <returns>
/// A value between <paramref name="start"/> and <paramref name="finish"/> as determined
/// by <paramref name="progress"/>.
/// </returns>
T Ease(double progress, T start, T finish);
}
}

41
src/Avalonia.Animation/LinearDoubleEasing.cs

@ -1,41 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Animation
{
/// <summary>
/// Linearly eases a double value.
/// </summary>
public class LinearDoubleEasing : IEasing<double>
{
/// <summary>
/// Returns the value of the transition for the specified progress.
/// </summary>
/// <param name="progress">The progress of the transition, from 0 to 1.</param>
/// <param name="start">The start value of the transition.</param>
/// <param name="finish">The end value of the transition.</param>
/// <returns>
/// A value between <paramref name="start"/> and <paramref name="finish"/> as determined
/// by <paramref name="progress"/>.
/// </returns>
public double Ease(double progress, double start, double finish)
{
return ((finish - start) * progress) + start;
}
/// <summary>
/// Returns the value of the transition for the specified progress.
/// </summary>
/// <param name="progress">The progress of the transition, from 0 to 1.</param>
/// <param name="start">The start value of the transition.</param>
/// <param name="finish">The end value of the transition.</param>
/// <returns>
/// A value between <paramref name="start"/> and <paramref name="finish"/> as determined
/// by <paramref name="progress"/>.
/// </returns>
object IEasing.Ease(double progress, object start, object finish)
{
return Ease(progress, (double)start, (double)finish);
}
}
}

35
src/Avalonia.Animation/LinearEasing.cs

@ -1,35 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Animation
{
/// <summary>
/// Returns a linear <see cref="IEasing"/> for the specified type.
/// </summary>
/// <remarks>
/// Unfortunately this class is needed as there's no way to create a true generic easing
/// function at compile time, as mathematical operators don't have an interface.
/// </remarks>
public static class LinearEasing
{
/// <summary>
/// A linear easing function for the specified type.
/// </summary>
/// <typeparam name="T">The type.</typeparam>
/// <returns>An easing function.</returns>
public static IEasing<T> For<T>()
{
if (typeof(T) == typeof(double))
{
return (IEasing<T>)new LinearDoubleEasing();
}
else
{
throw new NotSupportedException(
$"Don't know how to create a LinearEasing for type '{typeof(T).FullName}'.");
}
}
}
}

2
src/Avalonia.Animation/Properties/AssemblyInfo.cs

@ -1,6 +1,8 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Avalonia.Metadata;
using System.Reflection;
[assembly: AssemblyTitle("Avalonia.Animation")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Animation")]

50
src/Avalonia.Animation/PropertyTransition.cs

@ -1,50 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Animation
{
/// <summary>
/// Defines how a property should be animated using a transition.
/// </summary>
public class PropertyTransition
{
/// <summary>
/// Initializes a new instance of the <see cref="PropertyTransition"/> class.
/// </summary>
/// <param name="property">The property to be animated/</param>
/// <param name="duration">The duration of the animation.</param>
/// <param name="easing">The easing function to use.</param>
public PropertyTransition(AvaloniaProperty property, TimeSpan duration, IEasing easing)
{
Property = property;
Duration = duration;
Easing = easing;
}
/// <summary>
/// Gets the property to be animated.
/// </summary>
/// <value>
/// The property to be animated.
/// </value>
public AvaloniaProperty Property { get; }
/// <summary>
/// Gets the duration of the animation.
/// </summary>
/// <value>
/// The duration of the animation.
/// </value>
public TimeSpan Duration { get; }
/// <summary>
/// Gets the easing function used.
/// </summary>
/// <value>
/// The easing function.
/// </value>
public IEasing Easing { get; }
}
}

57
src/Avalonia.Animation/Animate.cs → src/Avalonia.Animation/Timing.cs

@ -11,9 +11,9 @@ using Avalonia.Threading;
namespace Avalonia.Animation
{
/// <summary>
/// Utilities for creating animations.
/// Provides global timing functions for animations.
/// </summary>
public static class Animate
public static class Timing
{
/// <summary>
/// The number of frames per second.
@ -26,9 +26,9 @@ namespace Avalonia.Animation
private static readonly TimeSpan Tick = TimeSpan.FromSeconds(1.0 / FramesPerSecond);
/// <summary>
/// Initializes static members of the <see cref="Animate"/> class.
/// Initializes static members of the <see cref="Timing"/> class.
/// </summary>
static Animate()
static Timing()
{
Stopwatch = new Stopwatch();
Stopwatch.Start();
@ -46,7 +46,8 @@ namespace Avalonia.Animation
/// </value>
public static Stopwatch Stopwatch
{
get; }
get;
}
/// <summary>
/// Gets the animation timer.
@ -61,7 +62,8 @@ namespace Avalonia.Animation
/// </value>
public static IObservable<TimeSpan> Timer
{
get; }
get;
}
/// <summary>
/// Gets a timer that fires every frame for the specified duration.
@ -86,49 +88,6 @@ namespace Avalonia.Animation
.Concat(Observable.Return(1.0));
}
/// <summary>
/// Animates a <see cref="AvaloniaProperty"/>.
/// </summary>
/// <param name="target">The target object.</param>
/// <param name="property">The target property.</param>
/// <param name="start">The value of the property at the start of the animation.</param>
/// <param name="finish">The value of the property at the end of the animation.</param>
/// <param name="easing">The easing function to use.</param>
/// <param name="duration">The duration of the animation.</param>
/// <returns>An <see cref="Animation"/> that can be used to track or stop the animation.</returns>
public static Animation Property(
IAvaloniaObject target,
AvaloniaProperty property,
object start,
object finish,
IEasing easing,
TimeSpan duration)
{
var o = GetTimer(duration).Select(progress => easing.Ease(progress, start, finish));
return new Animation(o, target.Bind(property, o, BindingPriority.Animation));
}
/// <summary>
/// Animates a <see cref="AvaloniaProperty"/>.
/// </summary>
/// <typeparam name="T">The property type.</typeparam>
/// <param name="target">The target object.</param>
/// <param name="property">The target property.</param>
/// <param name="start">The value of the property at the start of the animation.</param>
/// <param name="finish">The value of the property at the end of the animation.</param>
/// <param name="easing">The easing function to use.</param>
/// <param name="duration">The duration of the animation.</param>
/// <returns>An <see cref="Animation"/> that can be used to track or stop the animation.</returns>
public static Animation<T> Property<T>(
IAvaloniaObject target,
AvaloniaProperty<T> property,
T start,
T finish,
IEasing<T> easing,
TimeSpan duration)
{
var o = GetTimer(duration).Select(progress => easing.Ease(progress, start, finish));
return new Animation<T>(o, target.Bind(property, o, BindingPriority.Animation));
}
}
}

32
src/Avalonia.Animation/Transitions/DoubleTransition.cs

@ -0,0 +1,32 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Avalonia.Metadata;
using System;
namespace Avalonia.Animation
{
/// <summary>
/// Transitions object that handles properties with <see cref="double"/> types.
/// </summary>
public class DoubleTransition : Transition<double>
{
/// <inheritdocs/>
public DoubleTransition() : base()
{
}
/// <inheritdocs/>
public override AvaloniaProperty Property { get; set; }
/// <inheritdocs/>
public override void Apply(Animatable control)
{
//throw new NotImplementedException();
}
}
}

59
src/Avalonia.Animation/Transitions/Transition.cs

@ -0,0 +1,59 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Avalonia.Metadata;
using System;
namespace Avalonia.Animation
{
public interface ITransition
{
/// <summary>
/// Applies the transition to the specified <see cref="Animatable"/>.
/// </summary>
/// <param name="control"></param>
void Apply(Animatable control);
/// <summary>
/// Gets the property to be animated.
/// </summary>
AvaloniaProperty Property { get; set; }
}
/// <summary>
/// Defines how a property should be animated using a transition.
/// </summary>
public abstract class Transition<T> : ITransition
{
/// <summary>
/// Gets the duration of the animation.
/// </summary>
public TimeSpan Duration { get; set; }
/// <summary>
/// Instantiates the base abstract class <see cref="Transition{T}"/>.
/// </summary>
public Transition()
{
if(!(typeof(T) == Property.PropertyType))
{
throw new InvalidCastException
($"Invalid property type {typeof(T).Name} for this {this.GetType().Name}");
}
}
/// <summary>
/// Gets the easing class to be used.
/// </summary>
public IEasing Easing { get; set; }
/// <inheritdocs/>
public abstract AvaloniaProperty Property { get; set; }
/// <inheritdocs/>
public abstract void Apply(Animatable control);
}
}

8
src/Avalonia.Animation/PropertyTransitions.cs → src/Avalonia.Animation/Transitions/Transitions.cs

@ -6,14 +6,14 @@ using Avalonia.Collections;
namespace Avalonia.Animation
{
/// <summary>
/// A collection of <see cref="PropertyTransition"/> definitions.
/// A collection of <see cref="Transition"/> definitions.
/// </summary>
public class PropertyTransitions : AvaloniaList<PropertyTransition>
public class Transitions : AvaloniaList<ITransition>
{
/// <summary>
/// Initializes a new instance of the <see cref="PropertyTransitions"/> class.
/// Initializes a new instance of the <see cref="Transitions"/> class.
/// </summary>
public PropertyTransitions()
public Transitions()
{
ResetBehavior = ResetBehavior.Remove;
}

12
src/Avalonia.Controls/ProgressBar.cs

@ -114,12 +114,12 @@ namespace Avalonia.Controls
private IndeterminateAnimation(ProgressBar progressBar)
{
_progressBar = new WeakReference<ProgressBar>(progressBar);
_startTime = Animate.Stopwatch.Elapsed;
_indeterminateBindSubscription = Animate.Timer.TakeWhile(x => (x - _startTime).TotalSeconds <= 4.0)
.Select(GetAnimationRect)
.Finally(() => _startTime = Animate.Stopwatch.Elapsed)
.Repeat()
.Subscribe(AnimationTick);
//_startTime = Animate.Stopwatch.Elapsed;
//_indeterminateBindSubscription = Animate.Timer.TakeWhile(x => (x - _startTime).TotalSeconds <= 4.0)
// .Select(GetAnimationRect)
// .Finally(() => _startTime = Animate.Stopwatch.Elapsed)
// .Repeat()
// .Subscribe(AnimationTick);
}
public static IndeterminateAnimation StartAnimation(ProgressBar progressBar)

30
src/Avalonia.Visuals/Animation/CrossFade.cs

@ -58,13 +58,13 @@ namespace Avalonia.Animation
if (from != null)
{
tasks.Add(Animate.Property(
(IAvaloniaObject)from,
Visual.OpacityProperty,
from.Opacity,
0,
LinearEasing.For<double>(),
Duration).ToTask());
//tasks.Add(Animate.Property(
// (IAvaloniaObject)from,
// Visual.OpacityProperty,
// from.Opacity,
// 0,
// LinearEasing.For<double>(),
// Duration).ToTask());
}
if (to != null)
@ -72,16 +72,16 @@ namespace Avalonia.Animation
to.Opacity = 0;
to.IsVisible = true;
tasks.Add(Animate.Property(
(IAvaloniaObject)to,
Visual.OpacityProperty,
0,
1,
LinearEasing.For<double>(),
Duration).ToTask());
//tasks.Add(Animate.Property(
// (IAvaloniaObject)to,
// Visual.OpacityProperty,
// 0,
// 1,
// LinearEasing.For<double>(),
// Duration).ToTask());
}
await Task.WhenAll(tasks.ToArray());
//await Task.WhenAll(tasks.ToArray());
if (from != null)
{

30
src/Avalonia.Visuals/Animation/PageSlide.cs

@ -78,13 +78,13 @@ namespace Avalonia.Animation
{
var transform = new TranslateTransform();
from.RenderTransform = transform;
tasks.Add(Animate.Property(
transform,
translateProperty,
0.0,
forward ? -distance : distance,
LinearEasing.For<double>(),
Duration).ToTask());
//tasks.Add(Animate.Property(
// transform,
// translateProperty,
// 0.0,
// forward ? -distance : distance,
// LinearEasing.For<double>(),
// Duration).ToTask());
}
if (to != null)
@ -92,16 +92,16 @@ namespace Avalonia.Animation
var transform = new TranslateTransform();
to.RenderTransform = transform;
to.IsVisible = true;
tasks.Add(Animate.Property(
transform,
translateProperty,
forward ? distance : -distance,
0.0,
LinearEasing.For<double>(),
Duration).ToTask());
//tasks.Add(Animate.Property(
// transform,
// translateProperty,
// forward ? distance : -distance,
// 0.0,
// LinearEasing.For<double>(),
// Duration).ToTask());
}
await Task.WhenAll(tasks.ToArray());
//await Task.WhenAll(tasks.ToArray());
if (from != null)
{

1
src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj

@ -31,6 +31,7 @@
</Compile>
<Compile Include="AvaloniaXamlLoaderPortableXaml.cs" />
<Compile Include="AvaloniaXamlLoader.cs" />
<Compile Include="Converters\EasingTypeConverter.cs" />
<Compile Include="Converters\MatrixTypeConverter.cs" />
<Compile Include="Converters\RectTypeConverter.cs" />
<Compile Include="Converters\SetterValueTypeConverter.cs" />

24
src/Markup/Avalonia.Markup.Xaml/Converters/EasingTypeConverter.cs

@ -0,0 +1,24 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Avalonia.Animation;
using System;
using System.ComponentModel;
using System.Globalization;
namespace Avalonia.Markup.Xaml.Converters
{
public class EasingTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return Easing.Parse((string)value);
}
}
}

2
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaDefaultTypeConverters.cs

@ -12,6 +12,7 @@ using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Collections;
using Avalonia.Controls.Templates;
using Avalonia.Animation;
namespace Avalonia.Markup.Xaml.PortableXaml
{
@ -47,6 +48,7 @@ namespace Avalonia.Markup.Xaml.PortableXaml
//{ typeof(Uri), typeof(Converters.UriTypeConverter) },
{ typeof(Cursor), typeof(CursorTypeConverter) },
{ typeof(WindowIcon), typeof(IconTypeConverter) },
{ typeof(Easing), typeof(EasingTypeConverter) },
//{ typeof(FontWeight), typeof(FontWeightConverter) },
};

Loading…
Cancel
Save