LoadingCircle.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. using System;
  2. using System.Windows;
  3. using System.Windows.Controls;
  4. using System.Windows.Data;
  5. using System.Windows.Media;
  6. using System.Windows.Media.Animation;
  7. using HandyControl.Data;
  8. namespace HandyControl.Controls;
  9. public class LoadingCircle : LoadingBase
  10. {
  11. public static readonly DependencyProperty DotOffSetProperty = DependencyProperty.Register(
  12. nameof(DotOffSet), typeof(double), typeof(LoadingCircle),
  13. new FrameworkPropertyMetadata(20.0, FrameworkPropertyMetadataOptions.AffectsRender));
  14. public double DotOffSet
  15. {
  16. get => (double) GetValue(DotOffSetProperty);
  17. set => SetValue(DotOffSetProperty, value);
  18. }
  19. public static readonly DependencyProperty NeedHiddenProperty = DependencyProperty.Register(
  20. nameof(NeedHidden), typeof(bool), typeof(LoadingCircle),
  21. new FrameworkPropertyMetadata(ValueBoxes.TrueBox, FrameworkPropertyMetadataOptions.AffectsRender));
  22. public bool NeedHidden
  23. {
  24. get => (bool) GetValue(NeedHiddenProperty);
  25. set => SetValue(NeedHiddenProperty, ValueBoxes.BooleanBox(value));
  26. }
  27. static LoadingCircle()
  28. {
  29. DotSpeedProperty.OverrideMetadata(typeof(LoadingCircle),
  30. new FrameworkPropertyMetadata(6.0, FrameworkPropertyMetadataOptions.AffectsRender));
  31. DotDelayTimeProperty.OverrideMetadata(typeof(LoadingCircle),
  32. new FrameworkPropertyMetadata(220.0, FrameworkPropertyMetadataOptions.AffectsRender));
  33. }
  34. protected sealed override void UpdateDots()
  35. {
  36. var dotCount = DotCount;
  37. var dotInterval = DotInterval;
  38. var dotSpeed = DotSpeed;
  39. var dotDelayTime = DotDelayTime;
  40. var needHidden = NeedHidden;
  41. if (dotCount < 1) return;
  42. PrivateCanvas.Children.Clear();
  43. //定义动画
  44. Storyboard = new Storyboard
  45. {
  46. RepeatBehavior = RepeatBehavior.Forever
  47. };
  48. //创建圆点
  49. for (var i = 0; i < dotCount; i++)
  50. {
  51. var border = CreateBorder(i, dotInterval, needHidden);
  52. var framesMove = new DoubleAnimationUsingKeyFrames
  53. {
  54. BeginTime = TimeSpan.FromMilliseconds(dotDelayTime * i)
  55. };
  56. var subAngle = -dotInterval * i;
  57. //开始位置
  58. var frame0 = new LinearDoubleKeyFrame
  59. {
  60. Value = 0 + subAngle,
  61. KeyTime = KeyTime.FromTimeSpan(TimeSpan.Zero)
  62. };
  63. //开始位置到第一次匀速开始
  64. var frame1 = new EasingDoubleKeyFrame
  65. {
  66. EasingFunction = new PowerEase
  67. {
  68. EasingMode = EasingMode.EaseOut
  69. },
  70. Value = 180 + subAngle,
  71. KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(dotSpeed * (0.75 / 7)))
  72. };
  73. //第一次匀速开始到第一次匀速结束
  74. var frame2 = new LinearDoubleKeyFrame
  75. {
  76. Value = 180 + DotOffSet + subAngle,
  77. KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(dotSpeed * (2.75 / 7)))
  78. };
  79. //第一次匀速结束到匀加速结束
  80. var frame3 = new EasingDoubleKeyFrame
  81. {
  82. EasingFunction = new PowerEase
  83. {
  84. EasingMode = EasingMode.EaseIn
  85. },
  86. Value = 360 + subAngle,
  87. KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(dotSpeed * (3.5 / 7)))
  88. };
  89. //匀加速结束到匀减速结束
  90. var frame4 = new EasingDoubleKeyFrame
  91. {
  92. EasingFunction = new PowerEase
  93. {
  94. EasingMode = EasingMode.EaseOut
  95. },
  96. Value = 540 + subAngle,
  97. KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(dotSpeed * (4.25 / 7)))
  98. };
  99. //匀减速结束到第二次匀速结束
  100. var frame5 = new LinearDoubleKeyFrame
  101. {
  102. Value = 540 + DotOffSet + subAngle,
  103. KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(dotSpeed * (6.25 / 7)))
  104. };
  105. //第二次匀速结束到匀加速结束
  106. var frame6 = new EasingDoubleKeyFrame
  107. {
  108. EasingFunction = new PowerEase
  109. {
  110. EasingMode = EasingMode.EaseIn
  111. },
  112. Value = 720 + subAngle,
  113. KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(dotSpeed))
  114. };
  115. framesMove.KeyFrames.Add(frame0);
  116. framesMove.KeyFrames.Add(frame1);
  117. framesMove.KeyFrames.Add(frame2);
  118. framesMove.KeyFrames.Add(frame3);
  119. framesMove.KeyFrames.Add(frame4);
  120. framesMove.KeyFrames.Add(frame5);
  121. framesMove.KeyFrames.Add(frame6);
  122. Storyboard.SetTarget(framesMove, border);
  123. Storyboard.SetTargetProperty(framesMove, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)"));
  124. Storyboard.Children.Add(framesMove);
  125. if (NeedHidden)
  126. {
  127. //隐藏一段时间
  128. var frame7 = new DiscreteObjectKeyFrame
  129. {
  130. Value = Visibility.Collapsed,
  131. KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(dotSpeed))
  132. };
  133. var frame8 = new DiscreteObjectKeyFrame
  134. {
  135. Value = Visibility.Collapsed,
  136. KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(dotSpeed + 0.4))
  137. };
  138. var frame9 = new DiscreteObjectKeyFrame
  139. {
  140. Value = Visibility.Visible,
  141. KeyTime = KeyTime.FromTimeSpan(TimeSpan.Zero)
  142. };
  143. var framesVisibility = new ObjectAnimationUsingKeyFrames
  144. {
  145. BeginTime = TimeSpan.FromMilliseconds(dotDelayTime * i)
  146. };
  147. framesVisibility.KeyFrames.Add(frame9);
  148. framesVisibility.KeyFrames.Add(frame7);
  149. framesVisibility.KeyFrames.Add(frame8);
  150. Storyboard.SetTarget(framesVisibility, border);
  151. Storyboard.SetTargetProperty(framesVisibility, new PropertyPath("(UIElement.Visibility)"));
  152. Storyboard.Children.Add(framesVisibility);
  153. }
  154. PrivateCanvas.Children.Add(border);
  155. }
  156. Storyboard.Begin();
  157. if (!IsRunning)
  158. {
  159. Storyboard.Pause();
  160. }
  161. }
  162. private Border CreateBorder(int index, double dotInterval, bool needHidden)
  163. {
  164. var ellipse = CreateEllipse(index);
  165. ellipse.HorizontalAlignment = HorizontalAlignment.Center;
  166. ellipse.VerticalAlignment = VerticalAlignment.Bottom;
  167. var rt = new RotateTransform
  168. {
  169. Angle = -dotInterval * index
  170. };
  171. var myTransGroup = new TransformGroup();
  172. myTransGroup.Children.Add(rt);
  173. var border = new Border
  174. {
  175. RenderTransformOrigin = new Point(0.5, 0.5),
  176. RenderTransform = myTransGroup,
  177. Child = ellipse,
  178. Visibility = needHidden ? Visibility.Collapsed : Visibility.Visible
  179. };
  180. border.SetBinding(WidthProperty, new Binding("Width") { Source = this });
  181. border.SetBinding(HeightProperty, new Binding("Height") { Source = this });
  182. return border;
  183. }
  184. }