RollOverAnimation.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Windows;
  5. using System.Windows.Controls;
  6. using System.Windows.Media;
  7. using System.Windows.Media.Animation;
  8. namespace Muchinfo.WPF.Controls.Animation
  9. {
  10. /// <summary>
  11. /// Class RollOverAnimation.
  12. /// </summary>
  13. [TemplatePart(Name = "NextItems", Type = typeof(ItemsControl))]
  14. [TemplatePart(Name = "CurrentItems", Type = typeof(ItemsControl))]
  15. public class RollOverAnimation : Control
  16. {
  17. static RollOverAnimation()
  18. {
  19. DefaultStyleKeyProperty.OverrideMetadata(typeof(RollOverAnimation), new FrameworkPropertyMetadata(typeof(RollOverAnimation)));
  20. }
  21. private const int C_steySeconds = 3;
  22. private const int C_PlaySeconds = 5;
  23. private Storyboard _rolloverStoryboard = new Storyboard();
  24. private DoubleAnimationUsingKeyFrames _currentAnimation;
  25. private DoubleAnimationUsingKeyFrames _nextAnimation;
  26. private ItemsControl _currentItems, _nextItems;
  27. /// <summary>
  28. /// 当前索引
  29. /// </summary>
  30. public int _currentIndex;
  31. public RollOverAnimation()
  32. {
  33. _currentAnimation = new DoubleAnimationUsingKeyFrames();
  34. _nextAnimation = new DoubleAnimationUsingKeyFrames();
  35. _rolloverStoryboard.Completed += _rolloverStoryboard_Completed;
  36. IsVisibleChanged += delegate(object sender, DependencyPropertyChangedEventArgs e)
  37. {
  38. if (false.Equals(e.NewValue))
  39. {
  40. _rolloverStoryboard.Stop(this);
  41. }
  42. };
  43. }
  44. /// <summary>
  45. /// 动画完成后切换
  46. /// </summary>
  47. /// <param name="sender"></param>
  48. /// <param name="e"></param>
  49. void _rolloverStoryboard_Completed(object sender, EventArgs e)
  50. {
  51. _rolloverStoryboard.Stop(this);
  52. PlayNextList();
  53. _rolloverStoryboard.Begin(this, true);
  54. }
  55. /// <summary>
  56. /// 显示行的样式
  57. /// </summary>
  58. public DataTemplate ItemsTemplate
  59. {
  60. get { return (DataTemplate)GetValue(ItemsTemplateProperty); }
  61. set { SetValue(ItemsTemplateProperty, value); }
  62. }
  63. // Using a DependencyProperty as the backing store for ItemsTemplate. This enables animation, styling, binding, etc...
  64. public static readonly DependencyProperty ItemsTemplateProperty =
  65. DependencyProperty.Register("ItemsTemplate", typeof(DataTemplate), typeof(RollOverAnimation), new PropertyMetadata(null));
  66. /// <summary>
  67. /// 绑定的数据源
  68. /// </summary>
  69. public IList ItemsSource
  70. {
  71. get { return (IList)GetValue(ItemsSourceProperty); }
  72. set { SetValue(ItemsSourceProperty, value); }
  73. }
  74. // Using a DependencyProperty as the backing store for ItemsSource. This enables animation, styling, binding, etc...
  75. public static readonly DependencyProperty ItemsSourceProperty =
  76. DependencyProperty.Register("ItemsSource", typeof(IList), typeof(RollOverAnimation), new PropertyMetadata(null, OnItemsSourceChange));
  77. /// <summary>
  78. /// 当前显示的项
  79. /// </summary>
  80. public IList CurrentList
  81. {
  82. get { return (IList)GetValue(CurrentListProperty); }
  83. set { SetValue(CurrentListProperty, value); }
  84. }
  85. // Using a DependencyProperty as the backing store for CurrentList. This enables animation, styling, binding, etc...
  86. public static readonly DependencyProperty CurrentListProperty =
  87. DependencyProperty.Register("CurrentList", typeof(IList), typeof(RollOverAnimation), new PropertyMetadata(null));
  88. /// <summary>
  89. /// 即将显示的项
  90. /// </summary>
  91. public IList NextList
  92. {
  93. get { return (IList)GetValue(NextListProperty); }
  94. set { SetValue(NextListProperty, value); }
  95. }
  96. // Using a DependencyProperty as the backing store for NextList. This enables animation, styling, binding, etc...
  97. public static readonly DependencyProperty NextListProperty =
  98. DependencyProperty.Register("NextList", typeof(IList), typeof(RollOverAnimation), new PropertyMetadata(null));
  99. /// <summary>
  100. /// 每次显示的数量
  101. /// </summary>
  102. public int ShowCount
  103. {
  104. get { return (int)GetValue(ShowCountProperty); }
  105. set { SetValue(ShowCountProperty, value); }
  106. }
  107. // Using a DependencyProperty as the backing store for ShowIndex. This enables animation, styling, binding, etc...
  108. public static readonly DependencyProperty ShowCountProperty =
  109. DependencyProperty.Register("ShowCount", typeof(int), typeof(RollOverAnimation), new PropertyMetadata(3));
  110. /// <summary>
  111. /// 当数据源改变时重新进行动画
  112. /// </summary>
  113. /// <param name="d"></param>
  114. /// <param name="e"></param>
  115. public static void OnItemsSourceChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
  116. {
  117. var self = d as RollOverAnimation;
  118. if (self != null)
  119. {
  120. self.InitSourceAndPlay();
  121. }
  122. }
  123. /// <summary>
  124. /// 初始化数据并运行动画
  125. /// </summary>
  126. private void InitSourceAndPlay()
  127. {
  128. if (ItemsSource != null && ItemsSource.Count > 0)
  129. {
  130. _rolloverStoryboard.Stop(this);
  131. _currentIndex = 0;
  132. if (ItemsSource.Count > ShowCount)
  133. {
  134. var list = new List<object>();
  135. var nextlist = new List<object>();
  136. int nextIndex = ShowCount;
  137. for (int i = 0; i < ShowCount; i++)
  138. {
  139. list.Add(ItemsSource[i]);
  140. if (nextIndex < ItemsSource.Count)
  141. {
  142. nextlist.Add(ItemsSource[nextIndex]);
  143. nextIndex++;
  144. }
  145. }
  146. _currentIndex = ShowCount - 1;
  147. CurrentList = list;
  148. NextList = nextlist;
  149. _rolloverStoryboard.Begin(this, true);
  150. }
  151. else
  152. {
  153. CurrentList = ItemsSource;
  154. }
  155. }
  156. }
  157. /// <summary>
  158. /// 播放一下个动画
  159. /// </summary>
  160. private void PlayNextList()
  161. {
  162. if (ItemsSource != null)
  163. {
  164. CurrentList = NextList;
  165. int tempflag = _currentIndex + NextList.Count;
  166. _currentIndex = tempflag > ItemsSource.Count - 1 ? NextList.Count - 1 : tempflag;
  167. //if (_currentIndex >= ItemsSource.Count-1)
  168. //{
  169. // _currentIndex = 0;
  170. //}
  171. tempflag = _currentIndex >= ItemsSource.Count - 1 ? 0 : _currentIndex + 1;
  172. var nextList = new List<object>();
  173. for (int i = tempflag; i < tempflag + ShowCount; i++)
  174. {
  175. if (i < ItemsSource.Count)
  176. {
  177. nextList.Add(ItemsSource[i]);
  178. }
  179. }
  180. NextList = nextList;
  181. }
  182. }
  183. public override void OnApplyTemplate()
  184. {
  185. _currentItems = GetTemplateChild("CurrentItems") as ItemsControl;
  186. _nextItems = GetTemplateChild("NextItems") as ItemsControl;
  187. base.OnApplyTemplate();
  188. }
  189. protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
  190. {
  191. if (_currentItems != null && _nextItems != null)
  192. {
  193. _currentAnimation.KeyFrames.Clear();
  194. _currentAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0))));
  195. _currentAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(C_steySeconds))));
  196. _currentAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(-this.ActualHeight, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(C_PlaySeconds))));
  197. _nextAnimation.KeyFrames.Clear();
  198. _nextAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(this.ActualHeight, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0))));
  199. _nextAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(this.ActualHeight, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(C_steySeconds))));
  200. _nextAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(C_PlaySeconds))));
  201. Storyboard.SetTarget(_currentAnimation, _currentItems);
  202. Storyboard.SetTargetProperty(_currentAnimation, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.Y)"));
  203. Storyboard.SetTarget(_nextAnimation, _nextItems);
  204. Storyboard.SetTargetProperty(_nextAnimation, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.Y)"));
  205. _rolloverStoryboard.Children.Add(_currentAnimation);
  206. _rolloverStoryboard.Children.Add(_nextAnimation);
  207. this.Clip = new RectangleGeometry(new Rect(new Point(), new Size(this.ActualWidth, this.ActualHeight)));
  208. }
  209. base.OnRenderSizeChanged(sizeInfo);
  210. }
  211. }
  212. }