GeometryAnimation.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. using System.Globalization;
  2. using System.Text.RegularExpressions;
  3. using System.Windows;
  4. using System.Windows.Media;
  5. using System.Windows.Media.Animation;
  6. using HandyControl.Data;
  7. using HandyControl.Tools;
  8. // ReSharper disable PossibleInvalidOperationException
  9. namespace HandyControl.Media.Animation;
  10. public class GeometryAnimation : GeometryAnimationBase
  11. {
  12. private string[] _strings;
  13. private double[] _numbersFrom;
  14. private double[] _numbersTo;
  15. private double[] _numbersAccumulator;
  16. public GeometryAnimation()
  17. {
  18. }
  19. public GeometryAnimation(string fromValue, string toValue) : this()
  20. {
  21. From = Geometry.Parse(fromValue);
  22. To = Geometry.Parse(toValue);
  23. }
  24. private void UpdateValue()
  25. {
  26. if (_numbersFrom == null || _numbersTo == null || _numbersFrom.Length != _numbersTo.Length) return;
  27. _numbersAccumulator = new double[_numbersFrom.Length];
  28. for (var i = 0; i < _numbersFrom.Length; i++)
  29. {
  30. _numbersAccumulator[i] = _numbersTo[i] - _numbersFrom[i];
  31. }
  32. }
  33. public GeometryAnimation(Geometry fromValue, Geometry toValue) : this()
  34. {
  35. From = fromValue;
  36. To = toValue;
  37. }
  38. public GeometryAnimation(Geometry fromValue, Geometry toValue, Duration duration) : this()
  39. {
  40. From = fromValue;
  41. To = toValue;
  42. Duration = duration;
  43. }
  44. public GeometryAnimation(Geometry fromValue, Geometry toValue, Duration duration, FillBehavior fillBehavior) : this()
  45. {
  46. From = fromValue;
  47. To = toValue;
  48. Duration = duration;
  49. FillBehavior = fillBehavior;
  50. }
  51. public new GeometryAnimation Clone() => (GeometryAnimation) base.Clone();
  52. protected override Freezable CreateInstanceCore() => new GeometryAnimation();
  53. protected override Geometry GetCurrentValueCore(Geometry defaultOriginValue, Geometry defaultDestinationValue, AnimationClock animationClock)
  54. {
  55. if (_numbersAccumulator == null)
  56. {
  57. if (_numbersFrom == null)
  58. {
  59. var geometryStr = defaultOriginValue.ToString(CultureInfo.InvariantCulture);
  60. AnimationHelper.DecomposeGeometryStr(geometryStr, out _numbersFrom);
  61. }
  62. if (_numbersTo == null)
  63. {
  64. var geometryStr = defaultDestinationValue.ToString(CultureInfo.InvariantCulture);
  65. AnimationHelper.DecomposeGeometryStr(geometryStr, out _numbersTo);
  66. _strings = Regex.Split(geometryStr, RegexPatterns.DigitsPattern);
  67. }
  68. UpdateValue();
  69. }
  70. if (_numbersAccumulator == null) return defaultOriginValue;
  71. var progress = animationClock.CurrentProgress.Value;
  72. var easingFunction = EasingFunction;
  73. if (easingFunction != null)
  74. {
  75. progress = easingFunction.Ease(progress);
  76. }
  77. var accumulated = new double[_numbersAccumulator.Length];
  78. if (IsCumulative)
  79. {
  80. var currentRepeat = (double) (animationClock.CurrentIteration - 1);
  81. if (currentRepeat > 0.0)
  82. {
  83. accumulated = new double[_numbersAccumulator.Length];
  84. for (var i = 0; i < _numbersAccumulator.Length; i++)
  85. {
  86. accumulated[i] = _numbersAccumulator[i] * currentRepeat;
  87. }
  88. }
  89. }
  90. var numbers = new double[_numbersAccumulator.Length];
  91. for (var i = 0; i < _numbersAccumulator.Length; i++)
  92. {
  93. numbers[i] = accumulated[i] + _numbersFrom[i] + _numbersAccumulator[i] * progress;
  94. }
  95. return AnimationHelper.ComposeGeometry(_strings, numbers);
  96. }
  97. public static readonly DependencyProperty FromProperty = DependencyProperty.Register(
  98. nameof(From), typeof(Geometry), typeof(GeometryAnimation), new PropertyMetadata(default(Geometry), OnFromChanged));
  99. private static void OnFromChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  100. {
  101. var obj = (GeometryAnimation) d;
  102. if (e.NewValue is Geometry geometry)
  103. {
  104. AnimationHelper.DecomposeGeometryStr(geometry.ToString(CultureInfo.InvariantCulture), out obj._numbersFrom);
  105. obj.UpdateValue();
  106. }
  107. }
  108. public Geometry From
  109. {
  110. get => (Geometry) GetValue(FromProperty);
  111. set => SetValue(FromProperty, value);
  112. }
  113. public static readonly DependencyProperty ToProperty = DependencyProperty.Register(
  114. nameof(To), typeof(Geometry), typeof(GeometryAnimation), new PropertyMetadata(default(Geometry), OnToChanged));
  115. private static void OnToChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  116. {
  117. var obj = (GeometryAnimation) d;
  118. if (e.NewValue is Geometry geometry)
  119. {
  120. var geometryStr = geometry.ToString(CultureInfo.InvariantCulture);
  121. AnimationHelper.DecomposeGeometryStr(geometryStr, out obj._numbersTo);
  122. obj._strings = Regex.Split(geometryStr, RegexPatterns.DigitsPattern);
  123. obj.UpdateValue();
  124. }
  125. }
  126. public Geometry To
  127. {
  128. get => (Geometry) GetValue(ToProperty);
  129. set => SetValue(ToProperty, value);
  130. }
  131. public static readonly DependencyProperty EasingFunctionProperty = DependencyProperty.Register(
  132. nameof(EasingFunction), typeof(IEasingFunction), typeof(GeometryAnimation), new PropertyMetadata(default(IEasingFunction)));
  133. public IEasingFunction EasingFunction
  134. {
  135. get => (IEasingFunction) GetValue(EasingFunctionProperty);
  136. set => SetValue(EasingFunctionProperty, value);
  137. }
  138. public bool IsCumulative
  139. {
  140. get => (bool) GetValue(IsCumulativeProperty);
  141. set => SetValue(IsCumulativeProperty, ValueBoxes.BooleanBox(value));
  142. }
  143. }