GDI+简单现实文字旋转

  1. 云栖社区>
  2. 博客>
  3. 正文

GDI+简单现实文字旋转

杰克.陈 2013-09-05 09:07:00 浏览556

原文 http://www.cnblogs.com/kaixiangbb/p/3301272.html

题记

    入职新公司已快有两月了,试用期已快结束,项目却迟迟还未正式启动。安排给我的多是些琐事,一直未进入工作状态。公司也不在本地,我是属于公司在现场招 的,工作地点就在客户这边。刚来时还有其他几个到这边出差的同事,有专门过来带我熟悉业务的,但呆了一个月陆陆续续都回公司去了。现目前就我和另一个在这 边上学的研三的实习生同事,没有人管着又没多少事可做,着实闲得有点蛋疼。

    一闲下来时间似乎就停滞了,博客园不知道刷新了多少次,可电脑右下角的时间距离下班还是那么长。浏览器关了又打开,重复了N多次,一遍一遍的F5多么期待 能够出现一篇耳目一新的博文,能够把我的游离灵魂带走,忘记那等待的煎熬。忙起来的时候,看的QQ群图标不停的在眼角余光中闪烁,不由得会烦躁起来,于是 立马屏蔽掉所有群消息。带上耳机静静地听着音乐,思考问题、敲打代码,一心只为写代码,两耳不闻窗外事。而这久,一看到群里有动静,不管啥话题,管它什么 人,都要去凑凑热闹,插个三言两语。特别是前不久博客园里争论.net与java的话题,我一看到这样的博文,会不由自主的把标题附带链接发到群里。结果 成为众矢之的,过街老鼠,人人喊打,都在骂我@#¥%……&*。看到群里顿时热闹起来,我到觉得骂我的不是事,反而有种优越感......。当 然,除了这些水话外,也经常有新手遇到问题时到群里提问的,大多都是些很入门级的基础知识,其实只要用好百度、msdn用点心都很容易解决问题的。止住, 啰哩啰嗦说了这么多水话,还是步入正题吧。

1、问题是这样的

     在QQ群里有同学问GDI+如何实现文字旋转,实现的效果如下图:

     

    看到这图还是有点意思的,因为自己没实现过,对GDI+也比较陌生又比较好奇。之前虽然接触过这方面的知识,但并不是很了解也仅限于皮毛。不过看到图的一 瞬间给我的感觉是也不难实现么,动下脑子思路已浮现出来。和这位同学大概说了下思路,具体的参考可以去百度上搜索,应该会有这方面的例子,.net基础的 知识在网上还是很容易搜到的。毕竟自己也是这样学习过来,一路成长起来,很多问题自己下点功夫、花点心思都能解决,没必要一碰到问题不经大脑思考就到处发 问。

    第二天,这同学又在群里发问了,我很是纳闷难道网上找不到这方面的例子,真心有这么难么。于是和群里另一个朋友一起数落了下他,看看他是回答的如此心安理 得。我说:"你是不是学生,要多动脑筋",他答:"比学生还学生,不懂",朋友说:"基础不牢 一切都是浮云",他答:"没有基础"。最让我无语的是,因为自己闲着没事于是简单的做了个demo发给他,是用winform实现的。然后这位同学貌似很 急切的问我说:"你做的是winform平台,我做惯了网页平台,报了个错,看下",附带报错的截图。一看把小伙伴们都惊呆了,原来他直接把 form.cs里的main方法一块复制张贴,我这个心情,真不知道要如何回答他。

    他那边能运行起来后,又开始发问了说:"怎么是固定的?不能生成一次变一次吗"、"asp.net中有没有随机旋转位置的函数,而不是这种有规律的"。我 做的简单,数字没随机生成,而是1、2、3...这样顺序的,并且旋转的角度是每次在上一次的基础上加上一个固定的旋转偏移量,然后就有了前面的问题。我 以为他不知道.net里的Random随机数对象,特地和他说了下,可以百度一下。结果他答:"嗯,这个是产生随机数,不过现在数字可以不变,我想让位置 随机,不知道有没有这样的函数,在此百度也是一样的"。我的小伙伴们我惊恐万分啊,真心只想来句,"草泥马戈壁,SB啊"。我承认我思想有点不纯洁,好在 忍了会又随口水一起咽回去了。

    群里的那位朋友似乎也被惊呆了,按耐不住又开始数落这位同学,且看下精彩的对答吧,他问:"颜色是不是也可以随机啊?",我回:"动脑筋就可以",他 答:"基础差"。朋友回:"不是基础差,是不会举一反三",他答:"基础差,没信心,反三了怕不对",朋友很无奈狠狠的这样回了句:"你有一个JJ,你只会用它撒尿,不会用它日逼?"。我这双狗眼啊又再次被刺瞎了,然后群里纷纷接住这句话,不过都没文字,只发了个表情。看到这里,各位看官有何感想。这就是问题由来,下面就来解决问题吧。

2、实现

    使用随机数对象来实现随机的数字、文字颜色、旋转角度就不多说了。下面是我的实现思路,首先看实现旋转的这个方法 public void RotateTransform(float angle),这个是Graphics对象的一个实例方法,参数为旋转的角度(以度为单位)。也就是说是现实对整个绘图图面(Graphics对象)的旋 转,而不是针对画板里的单个元素。那么就不能实现创建一个画板,然后分别把随机的数字旋转位置后再画到画板上。我的办法是先创建单个数字的小画板进行旋转 后用Graphics对象的DrawImage方法把它们画到大的画板上,即:把单个数字的小位图合并为大图。旋转的时候要注意一点,默认画板的原坐标点 是在左上角,此时如果以这个点为基准进行旋转后,会发现上面的数字跑到了别的地方,其实道理很简单,拿张纸试下就知道了呗。所以在旋转前,需要改变画板的 坐标原点为中点,使用的是Graphics对象的TranslateTransform(Single, Single)方法,描述:通过使此 Graphics 的变换矩阵左乘指定的平移来更改坐标系统的原点。源码如下:

 

复制代码
 1         /// <summary>
 2         /// 生成单个小图
 3         /// </summary>
 4         /// <param name="s">数字</param>
 5         /// <param name="c">数字颜色</param>
 6         /// <param name="py">旋转偏移量</param>
 7         /// <returns></returns>
 8         public System.Drawing.Image BuildBitmap(string s, Color c,float py)
 9         {
10             System.Drawing.Bitmap bitmap = new Bitmap(140, 80);
11             var g = System.Drawing.Graphics.FromImage(bitmap);
12             g.Clear(Color.White);
13             //设置画板的坐标原点为中点
14             g.TranslateTransform(bitmap.Width/2, bitmap.Height/2);
15             //以指定角度对画板进行旋转
16             g.RotateTransform(py);
17             var size = g.MeasureString(s, new Font("arial", 48, FontStyle.Regular));
18             //让文字变得平滑
19             g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
20             //把数字画到画板的中点位置
21             g.DrawString(s, new Font("arial", 48, FontStyle.Regular), new SolidBrush(c), (bitmap.Width - size.Width) / 2 - bitmap.Width / 2, (bitmap.Height - size.Height) / 2 - bitmap.Height / 2);
22             return bitmap;
23         }
24 
25         /// <summary>
26         /// 把小图合并为一个大图
27         /// </summary>
28         public void BuildBigImage()
29         {
30             Color[] c = new Color[9] { Color.Red, Color.Green, Color.Maroon, Color.Blue, Color.BurlyWood, Color.Orange, Color.Lime, Color.MediumTurquoise, Color.Olive };
31             Bitmap bigImage = new Bitmap(420, 240);//创建一个大位图
32             Graphics g=Graphics.FromImage(bigImage);//创建大图的画板
33             Random r = new Random(DateTime.Now.Millisecond);
34             var x = 0;
35             var y = 0;
36             for (int i = 1; i < 10; i++)
37             {
38                 var color = c[r.Next(0, 8)];
39                 float py = r.Next(1, 36) * 10;//长生随机的偏移量
40                 var img = BuildBitmap(r.Next(1, 9).ToString(), color, py); 
41                 if (x == 420)
42                     x = 0;
43                 if (i <= 3)
44                 {
45                     var point = new Point(x, y);//小图画到大图上的位置
46                     g.DrawImage(img, point);//把小图画到大图上
47                 }
48                 else if (i > 3 && i <= 6)
49                 {
50                     y = 80;
51                     var point = new Point(x, y);
52                     g.DrawImage(img, point);//把小图画到大图上
53                 }
54                 else
55                 {
56                     y = 160;
57                     var point = new Point(x, y);
58                     g.DrawImage(img, point);//把小图画到大图上
59                 }
60                 x = x + 140;
61             }
62             //添加网格线
63             g.DrawLine(new Pen(new SolidBrush(Color.Gray), 1), new Point(0, 0), new Point(420, 0));
64             g.DrawLine(new Pen(new SolidBrush(Color.Gray), 1), new Point(0, 239), new Point(420, 239));
65             g.DrawLine(new Pen(new SolidBrush(Color.Gray), 1), new Point(0, 80), new Point(420, 80));
66             g.DrawLine(new Pen(new SolidBrush(Color.Gray), 1), new Point(0, 160), new Point(420, 160));
67             g.DrawLine(new Pen(new SolidBrush(Color.Gray), 1), new Point(140, 0), new Point(140, 240));
68             g.DrawLine(new Pen(new SolidBrush(Color.Gray), 1), new Point(280, 0), new Point(280, 240));
69             g.DrawLine(new Pen(new SolidBrush(Color.Gray), 1), new Point(0, 0), new Point(0, 240));
70             g.DrawLine(new Pen(new SolidBrush(Color.Gray), 1), new Point(419, 0), new Point(419, 240));
71             System.IO.MemoryStream sm = new System.IO.MemoryStream();
72             bigImage.Save(sm, System.Drawing.Imaging.ImageFormat.Png);
73             Response.ContentType = "image/png";
74             Response.BinaryWrite(sm.ToArray());
75         }
复制代码

 

 

 

   实现效果图如下:

  以上就是实现文字旋转的所有过程,虽然没有原图那么漂亮,不过原理应当如此。

  注册博客园已有一段时间了,但一直都是打酱油的角色,没写过几篇博文,如有不妥之处还望各位看官谅解给予指正,小弟在此谢过啦!