Tweener.cs 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. using Avalonia;
  2. using Avalonia.Animation.Easings;
  3. using Avalonia.Controls;
  4. using Avalonia.Threading;
  5. namespace PixiEditor.UI.Common.Tweening;
  6. public static class Tween
  7. {
  8. public static Tweener<double> Double(AvaloniaProperty<double> property, Control control,
  9. double endValue, double duration, IEasing easing = null)
  10. {
  11. return new Tweener<double>(property, control, endValue, duration,
  12. (start, end, t) => start + (end - start) * easing?.Ease(t) ?? t);
  13. }
  14. }
  15. public class Tweener<T>
  16. {
  17. public AvaloniaProperty<T> Property { get; }
  18. public T StartValue { get; private set; }
  19. public T EndValue { get; }
  20. public double DurationMs { get; }
  21. public Func<T, T, double, T> Interpolator { get; }
  22. public Control Control { get; set; }
  23. private DispatcherTimer timer;
  24. public Tweener(AvaloniaProperty<T> property, Control control, T endValue, double durationMs,
  25. Func<T, T, double, T> interpolator)
  26. {
  27. Property = property;
  28. EndValue = endValue;
  29. DurationMs = durationMs;
  30. Interpolator = interpolator;
  31. Control = control;
  32. }
  33. public Tweener<T> Run()
  34. {
  35. timer = new DispatcherTimer(DispatcherPriority.Default) { Interval = TimeSpan.FromMilliseconds(16) };
  36. DateTime startTime = DateTime.Now;
  37. StartValue = (T)Control.GetValue(Property);
  38. timer.Tick += (sender, args) =>
  39. {
  40. double elapsed = (DateTime.Now - startTime).TotalMilliseconds;
  41. if (elapsed >= DurationMs)
  42. {
  43. timer.Stop();
  44. Control.SetValue(Property, EndValue);
  45. return;
  46. }
  47. double t = elapsed / DurationMs;
  48. T value = Interpolator(StartValue, EndValue, t);
  49. Control.SetValue(Property, value);
  50. };
  51. timer.Start();
  52. return this;
  53. }
  54. public void Stop()
  55. {
  56. timer.Stop();
  57. Control.SetValue(Property, EndValue);
  58. }
  59. }