非常喜欢Metro风格的界面,所以想模仿一下一些UI效果的实现,网上找到了很多,但都是CSS3,WPF等实现,对于XAML和CSS3一窍不通,无奈下只有自己开始写。

下面是源码:

  1. 1 using System;
  2. 2 using System.ComponentModel;
  3. 3 using System.Drawing;
  4. 4 using System.Drawing.Drawing2D;
  5. 5 using System.Linq;
  6. 6 using System.Threading;
  7. 7 using System.Windows.Forms;
  8. 8 using ThreadingTimer = System.Threading.Timer;
  9. 9 using UITimer = System.Windows.Forms.Timer;
  10. 10
  11. 11 namespace LoadingCircle
  12. 12 {
  13. 13 /// <summary>
  14. 14 /// 表示一个加载圆圈动画
  15. 15 /// </summary>
  16. 16 [ToolboxBitmap(typeof (LoadingCircle), "LoadingCircleIcon.png")]
  17. 17 public partial class LoadingCircle : UserControl
  18. 18 {
  19. 19 #region 构造
  20. 20
  21. 21 public LoadingCircle()
  22. 22 {
  23. 23 InitializeComponent();
  24. 24
  25. 25 //双缓冲,禁擦背景
  26. 26 SetStyle(
  27. 27 ControlStyles.AllPaintingInWmPaint |
  28. 28 ControlStyles.UserPaint |
  29. 29 ControlStyles.OptimizedDoubleBuffer,
  30. 30 true);
  31. 31
  32. 32 //初始化绘图timer
  33. 33 _graphicsTmr = new UITimer {Interval = 1};
  34. 34 //Invalidate()强制重绘,绘图操作在OnPaint中实现
  35. 35 _graphicsTmr.Tick += (sender1, e1) => Invalidate(false);
  36. 36
  37. 37 _dotSize = Width/10f;
  38. 38
  39. 39 //初始化"点"
  40. 40 _dots = new Dot[5];
  41. 41
  42. 42 Color = Color.White;
  43. 43 }
  44. 44
  45. 45 #endregion 构造
  46. 46
  47. 47 #region 属性
  48. 48
  49. 49 /// <summary>
  50. 50 /// 圆心
  51. 51 /// </summary>
  52. 52 [Browsable(false)]
  53. 53 public PointF CircleCenter
  54. 54 {
  55. 55 get { return new PointF(Width/2f, Height/2f); }
  56. 56 }
  57. 57
  58. 58 /// <summary>
  59. 59 /// 半径
  60. 60 /// </summary>
  61. 61 [Browsable(false)]
  62. 62 public float CircleRadius
  63. 63 {
  64. 64 get { return Width/2f - _dotSize; }
  65. 65 }
  66. 66
  67. 67 /// <summary>
  68. 68 /// 颜色
  69. 69 /// </summary>
  70. 70 [Browsable(true), Category("Appearance"), Description("设置\"点\"的前景色")]
  71. 71 public Color Color { get; set; }
  72. 72
  73. 73 #endregion 属性
  74. 74
  75. 75 #region 字段
  76. 76
  77. 77 //点数组
  78. 78 private readonly Dot[] _dots;
  79. 79
  80. 80 //Timers
  81. 81 private readonly UITimer _graphicsTmr;
  82. 82 private ThreadingTimer _actionTmr;
  83. 83
  84. 84 //点大小
  85. 85 private float _dotSize;
  86. 86
  87. 87 //是否活动
  88. 88 private bool _isActived;
  89. 89
  90. 90 //是否绘制:用于状态重置时挂起与恢复绘图
  91. 91 private bool _isDrawing = true;
  92. 92
  93. 93 //Timer计数:用于延迟启动每个点
  94. 94 private int _timerCount;
  95. 95
  96. 96 #endregion 字段
  97. 97
  98. 98 #region 常量
  99. 99
  100. 100 //动作间隔(Timer)
  101. 101 private const int ActionInterval = 30;
  102. 102
  103. 103 //计数基数:用于计算每个点启动延迟:index * timerCountRadix
  104. 104 private const int TimerCountRadix = 45;
  105. 105
  106. 106 #endregion 常量
  107. 107
  108. 108 #region 方法
  109. 109
  110. 110 //检查是否重置
  111. 111 private bool CheckToReset()
  112. 112 {
  113. 113 return _dots.Count(d => d.Opacity > 0) == 0;
  114. 114 }
  115. 115
  116. 116 //初始化点元素
  117. 117 private void CreateDots()
  118. 118 {
  119. 119 for (int i = 0; i < _dots.Length; ++i)
  120. 120 _dots[i] = new Dot(CircleCenter, CircleRadius);
  121. 121 }
  122. 122
  123. 123 /// <summary>
  124. 124 /// 开关
  125. 125 /// </summary>
  126. 126 public bool Switch()
  127. 127 {
  128. 128 if (!_isActived)
  129. 129 Start();
  130. 130 else
  131. 131 Stop();
  132. 132
  133. 133 return _isActived;
  134. 134 }
  135. 135
  136. 136 /// <summary>
  137. 137 /// 开始
  138. 138 /// </summary>
  139. 139 public void Start()
  140. 140 {
  141. 141 CreateDots();
  142. 142
  143. 143 _timerCount = 0;
  144. 144 foreach (Dot dot in _dots)
  145. 145 dot.Reset();
  146. 146
  147. 147 _graphicsTmr.Start();
  148. 148
  149. 149 //初始化动作timer
  150. 150 _actionTmr = new ThreadingTimer(
  151. 151 state =>
  152. 152 {
  153. 153 //动画动作
  154. 154 for (int i = 0; i < _dots.Length; i++)
  155. 155 if (_timerCount++ > i * TimerCountRadix)
  156. 156 _dots[i].DotAction();
  157. 157
  158. 158 //是否重置
  159. 159 if (CheckToReset())
  160. 160 {
  161. 161 //重置前暂停绘图
  162. 162 _isDrawing = false;
  163. 163
  164. 164 _timerCount = 0;
  165. 165
  166. 166 foreach (Dot dot in _dots)
  167. 167 dot.Reset();
  168. 168
  169. 169 //恢复绘图
  170. 170 _isDrawing = true;
  171. 171 }
  172. 172
  173. 173 _actionTmr.Change(ActionInterval, Timeout.Infinite);
  174. 174 },
  175. 175 null, ActionInterval, Timeout.Infinite);
  176. 176
  177. 177 _isActived = true;
  178. 178 }
  179. 179
  180. 180 /// <summary>
  181. 181 /// 停止
  182. 182 /// </summary>
  183. 183 public void Stop()
  184. 184 {
  185. 185 _graphicsTmr.Stop();
  186. 186 _actionTmr.Dispose();
  187. 187 _isActived = false;
  188. 188 }
  189. 189
  190. 190 #endregion 方法
  191. 191
  192. 192 #region 重写
  193. 193
  194. 194 protected override void OnPaint(PaintEventArgs e)
  195. 195 {
  196. 196 if (_isActived && _isDrawing)
  197. 197 {
  198. 198 //抗锯齿
  199. 199 e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
  200. 200
  201. 201 using (var bmp = new Bitmap(200, 200))
  202. 202 {
  203. 203 //缓冲绘制
  204. 204 using (Graphics bufferGraphics = Graphics.FromImage(bmp))
  205. 205 {
  206. 206 //抗锯齿
  207. 207 bufferGraphics.SmoothingMode = SmoothingMode.HighQuality;
  208. 208 foreach (Dot dot in _dots)
  209. 209 {
  210. 210 var rect = new RectangleF(
  211. 211 new PointF(dot.Location.X - _dotSize/2, dot.Location.Y - _dotSize/2),
  212. 212 new SizeF(_dotSize, _dotSize));
  213. 213
  214. 214 bufferGraphics.FillEllipse(new SolidBrush(Color.FromArgb(dot.Opacity, Color)),
  215. 215 rect);
  216. 216 }
  217. 217 }
  218. 218
  219. 219 //贴图
  220. 220 e.Graphics.DrawImage(bmp, new PointF(0, 0));
  221. 221 } //bmp disposed
  222. 222 }
  223. 223
  224. 224 base.OnPaint(e);
  225. 225 }
  226. 226
  227. 227 protected override void OnResize(EventArgs e)
  228. 228 {
  229. 229 Height = Width;
  230. 230 _dotSize = Width/12f;
  231. 231
  232. 232 base.OnResize(e);
  233. 233 }
  234. 234
  235. 235 #endregion 重写
  236. 236 }
  237. 237 }

LoadingCircle.cs

  1. 1 using System.Drawing;
  2. 2
  3. 3 namespace LoadingCircle
  4. 4 {
  5. 5 /// <summary>
  6. 6 /// 表示一个"点"
  7. 7 /// </summary>
  8. 8 internal sealed class Dot
  9. 9 {
  10. 10 #region 字段/属性
  11. 11
  12. 12 //圆心
  13. 13 private readonly PointF _circleCenter;
  14. 14 //半径
  15. 15 private readonly float _circleRadius;
  16. 16
  17. 17 /// <summary>
  18. 18 /// 当前帧绘图坐标,在每次DotAction()时重新计算
  19. 19 /// </summary>
  20. 20 public PointF Location;
  21. 21
  22. 22 //点相对于圆心的角度,用于计算点的绘图坐标
  23. 23 private int _angle;
  24. 24 //透明度
  25. 25 private int _opacity;
  26. 26 //动画进度
  27. 27 private int _progress;
  28. 28 //速度
  29. 29 private int _speed;
  30. 30
  31. 31 /// <summary>
  32. 32 /// 透明度
  33. 33 /// </summary>
  34. 34 public int Opacity
  35. 35 {
  36. 36 get { return _opacity < MinOpacity ? MinOpacity : (_opacity > MaxOpacity ? MaxOpacity : _opacity); }
  37. 37 }
  38. 38
  39. 39 #endregion
  40. 40
  41. 41 #region 常量
  42. 42
  43. 43 //最小/最大速度
  44. 44 private const int MinSpeed = 2;
  45. 45 private const int MaxSpeed = 11;
  46. 46
  47. 47 //出现区的相对角度
  48. 48 private const int AppearAngle = 90;
  49. 49 //减速区的相对角度
  50. 50 private const int SlowAngle = 225;
  51. 51 //加速区的相对角度
  52. 52 private const int QuickAngle = 315;
  53. 53
  54. 54 //最小/最大角度
  55. 55 private const int MinAngle = 0;
  56. 56 private const int MaxAngle = 360;
  57. 57
  58. 58 //淡出速度
  59. 59 private const int AlphaSub = 25;
  60. 60
  61. 61 //最小/最大透明度
  62. 62 private const int MinOpacity = 0;
  63. 63 private const int MaxOpacity = 255;
  64. 64
  65. 65 #endregion 常量
  66. 66
  67. 67 #region 构造器
  68. 68
  69. 69 public Dot(PointF circleCenter, float circleRadius)
  70. 70 {
  71. 71 Reset();
  72. 72 _circleCenter = circleCenter;
  73. 73 _circleRadius = circleRadius;
  74. 74 }
  75. 75
  76. 76 #endregion 构造器
  77. 77
  78. 78 #region 方法
  79. 79
  80. 80 /// <summary>
  81. 81 /// 重新计算当前帧绘图坐标
  82. 82 /// </summary>
  83. 83 private void ReCalcLocation()
  84. 84 {
  85. 85 Location = Common.GetDotLocationByAngle(_circleCenter, _circleRadius, _angle);
  86. 86 }
  87. 87
  88. 88 /// <summary>
  89. 89 /// 点动作
  90. 90 /// </summary>
  91. 91 public void DotAction()
  92. 92 {
  93. 93 switch (_progress)
  94. 94 {
  95. 95 case 0:
  96. 96 {
  97. 97 _opacity = MaxOpacity;
  98. 98 AddSpeed();
  99. 99 if (_angle + _speed >= SlowAngle && _angle + _speed < QuickAngle)
  100. 100 {
  101. 101 _progress = 1;
  102. 102 _angle = SlowAngle - _speed;
  103. 103 }
  104. 104 }
  105. 105 break;
  106. 106 case 1:
  107. 107 {
  108. 108 SubSpeed();
  109. 109 if (_angle + _speed >= QuickAngle || _angle + _speed < SlowAngle)
  110. 110 {
  111. 111 _progress = 2;
  112. 112 _angle = QuickAngle - _speed;
  113. 113 }
  114. 114 }
  115. 115 break;
  116. 116 case 2:
  117. 117 {
  118. 118 AddSpeed();
  119. 119 if (_angle + _speed >= SlowAngle && _angle + _speed < QuickAngle)
  120. 120 {
  121. 121 _progress = 3;
  122. 122 _angle = SlowAngle - _speed;
  123. 123 }
  124. 124 }
  125. 125 break;
  126. 126 case 3:
  127. 127 {
  128. 128 SubSpeed();
  129. 129 if (_angle + _speed >= QuickAngle && _angle + _speed < MaxAngle)
  130. 130 {
  131. 131 _progress = 4;
  132. 132 _angle = QuickAngle - _speed;
  133. 133 }
  134. 134 }
  135. 135 break;
  136. 136 case 4:
  137. 137 {
  138. 138 SubSpeed();
  139. 139 if (_angle + _speed >= MinAngle && _angle + _speed < AppearAngle)
  140. 140 {
  141. 141 _progress = 5;
  142. 142 _angle = MinAngle;
  143. 143 }
  144. 144 }
  145. 145 break;
  146. 146 case 5:
  147. 147 {
  148. 148 AddSpeed();
  149. 149 FadeOut();
  150. 150 }
  151. 151 break;
  152. 152 }
  153. 153
  154. 154 //移动
  155. 155 _angle = _angle >= (MaxAngle - _speed) ? MinAngle : _angle + _speed;
  156. 156 //重新计算坐标
  157. 157 ReCalcLocation();
  158. 158 }
  159. 159
  160. 160 //淡出
  161. 161 private void FadeOut()
  162. 162 {
  163. 163 if ((_opacity -= AlphaSub) <= 0)
  164. 164 _angle = AppearAngle;
  165. 165 }
  166. 166
  167. 167 //重置状态
  168. 168 public void Reset()
  169. 169 {
  170. 170 _angle = AppearAngle;
  171. 171 _speed = MinSpeed;
  172. 172 _progress = 0;
  173. 173 _opacity = 1;
  174. 174 }
  175. 175
  176. 176 //加速
  177. 177 private void AddSpeed()
  178. 178 {
  179. 179 if (++_speed >= MaxSpeed) _speed = MaxSpeed;
  180. 180 }
  181. 181
  182. 182 //减速
  183. 183 private void SubSpeed()
  184. 184 {
  185. 185 if (--_speed <= MinSpeed) _speed = MinSpeed;
  186. 186 }
  187. 187
  188. 188 #endregion 方法
  189. 189 }
  190. 190 }

Dot.cs

  1. 1 using System;
  2. 2 using System.Drawing;
  3. 3
  4. 4 namespace LoadingCircle
  5. 5 {
  6. 6 public static class Common
  7. 7 {
  8. 8 /// <summary>
  9. 9 /// 根据半径、角度求圆上坐标
  10. 10 /// </summary>
  11. 11 /// <param name="center">圆心</param>
  12. 12 /// <param name="radius">半径</param>
  13. 13 /// <param name="angle">角度</param>
  14. 14 /// <returns>坐标</returns>
  15. 15 public static PointF GetDotLocationByAngle(PointF center, float radius, int angle)
  16. 16 {
  17. 17 var x = (float) (center.X + radius*Math.Cos(angle*Math.PI/180));
  18. 18 var y = (float) (center.Y + radius*Math.Sin(angle*Math.PI/180));
  19. 19
  20. 20 return new PointF(x, y);
  21. 21 }
  22. 22 }
  23. 23 }

Common.cs

附Demo链接,含控件源码:http://download.csdn.net/detail/coffee_mx/7510695

PS:有些地方肯定还有一些不协调,没办法,笔者审美有限,请大家通过代码内常量进行微调。欢迎大神们指点……

基于C#/Winform实现的Win8MetroLoading动画的更多相关文章

  1. 基于 SailingEase WinForm Framework 开发客户端程序(3:实现菜单/工具栏按钮的解耦及状态控制)

    本系列文章将详细阐述客户端应用程序的设计理念,实现方法. 本系列文章以  SailingEase WinForm Framework 为基础进行设计并实现,但其中的设计理念及方法,亦适用于任何类型的客 ...

  2. 基于 SailingEase WinForm Framework 开发优秀的客户端应用程序(目录)

    本系统文章将详细阐述客户端应用程序的设计理念,实现方法. 本系列文章以  SailingEase WinForm Framework 为基础进行设计并实现,但其中的设计理念及方法,亦适用于任何类型的客 ...

  3. 基于 SailingEase WinForm Framework 开发优秀的客户端应用程序(1:概述)

    本系统文章将详细阐述客户端应用程序的设计理念,实现方法. 本系列文章以  SailingEase WinForm Framework 为基础进行设计并实现,但其中的设计理念及方法,亦适用于任何类型的客 ...

  4. 基于jQuery点击加载动画按钮特效

    分享一款基于jQuery点击加载动画按钮特效.这是一款基于jQuery+CSS3实现的鼠标点击按钮加载动画特效代码.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div ...

  5. 基于html5页面滚动背景图片动画效果

    基于html5页面滚动背景图片动画效果是一款带索引按钮的页面滚动动画特效代码.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div id="fullpage&q ...

  6. 基于CSS3制作的鼠标悬停动画菜单

    之前分享了好多款css3实现的鼠标悬停效果.今天再给大家带来一款基于CSS3制作的鼠标悬停动画菜单.这款菜单适用浏览器:360.FireFox.Chrome.Safari.Opera.傲游.搜狗.世界 ...

  7. 基于jQuery弹出层图片动画查看代码

    分享一款基于jQuery弹出层图片动画查看代码是一款鼠标单击文字或图片内容放大显示且含圆角投影效果.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div class=&q ...

  8. 基于jQuery CSS3鼠标点击动画效果

    分享基于jQuery CSS3鼠标点击动画效果支持图片或内容滑动,允许设置动画延迟效果.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div class="co ...

  9. 30款基于 jQuery & CSS3 的加载动画和进度条插件

    我们所生活每一天看到的新技术或新设计潮流的兴起,Web 开发正处在上升的时代.HTML5 & CSS3 技术的发展让 Web 端可以实现的功能越来越强大. 加载动画和进度条使网站更具吸引力.该 ...

随机推荐

  1. RMI之由浅入深(一)

    0x01.什么是RMI RMI(Remote Method Invocation)即Java远程方法调用,RMI用于构建分布式应用程序,RMI实现了Java程序之间跨JVM的远程通信.顾名思义,远程方 ...

  2. mac强制关闭应用

    原文链接http://zhhll.icu/2020/08/13/Mac/%E5%BC%BA%E5%88%B6%E7%BB%88%E6%AD%A2%E5%BA%94%E7%94%A8/ 有时候使用Mac ...

  3. spring boot 邮件服务

    引入依赖 添加spring-boot-starter-mail包引用 <dependency> <groupId>org.springframework.boot</gr ...

  4. NodeJS各个平台安装详细

    http://www.runoob.com/nodejs/nodejs-install-setup.html 记录

  5. Unity优化 1

    浅谈Unity中的GC以及优化(转) Unity 官方文档,正巧在博客园发现了已经有位大神(zblade)把原文翻译出来了,而且质量很高~,译文地址 在这里.下面我就可耻地把译文搬运了过来,作为上面思 ...

  6. 【JDBC核心】JDBC 概述

    JDBC 概述 数据的持久化 持久化(persistence):把数据保存到可掉电式存储设备中以供之后使用.大多数情况下,特别是企业级应用,数据持久化意味着将内存中的数据保存到硬盘上加以"固 ...

  7. 十五:SQL注入之oracle,Mangodb注入

    Access,Mysql,mssql,mangoDB,postgresql,sqlite,oracle,sybase JSON类型的数据注入: 键名:键值 {"a":"1 ...

  8. 安装jdk-windows系统

    1. 明确需要安装的jdk版本,注意jdk存在小版本号,例如jdk1.7_51,如果不清楚小版本号的话建议安装最新版本的jdk: 2. 打开cmd命令窗口,输入java -version查看本机是否安 ...

  9. expect的使用

    1. expect概述 1.1 expect的功能 脚本执行时,有时会需要人工进行交互输入,这时可以通过expect工具来实现自动交互. expect是一种shell解释器,但是expect可以在命令 ...

  10. CSS实现迷你键盘

    最近做了一个迷你键盘的dome,这里分享给大家 dome下载地址(点击下载) 代码如下: <!DOCTYPE html> <html lang="en" > ...