zoukankan      html  css  js  c++  java
  • 《C# GDI+ 破境之道》:第一境 GDI+基础 —— 第三节:画圆形

    有了上一节画矩形的基础,画圆形就不要太轻松+EZ:)所以,本节在画边线及填充上,就不做过多的讲解了,关注一下画“随机椭圆”、“正圆”、“路径填充”的具体实现就好。与画矩形相比较,画椭圆与之完全一致,没有任何特别之处。

    在画矩形时,我们使用:

    • System.Drawing.Graphics.DrawRectangle(Brush brush, Rectangle rect);
    • System.Drawing.Graphics.FillRectangle(Brush brush, Rectangle rect);

    在画圆形时,我们使用:

    • System.Drawing.Graphics.DrawEllipse(Brush brush, Rectangle rect);
    • System.Drawing.Graphics.FillEllipse(Brush brush, Rectangle rect);

    看到了吧,就换了个方法名,参数连名都没换:)

    所以,了解了如何画矩形,画圆形就是自然掌握的了。

    本节就不多费口舌重复了:

      1 namespace MikeWare.GdiPlus.Ellipses
      2 {
      3     using System;
      4     using System.Collections.Generic;
      5     using System.Drawing;
      6     using System.Drawing.Drawing2D;
      7     using System.Windows.Forms;
      8 
      9     public partial class FormDrawEllipses : Form
     10     {
     11         private Random random = null;
     12         private Color penColor = Color.Transparent;
     13 
     14         public FormDrawEllipses()
     15         {
     16             InitializeComponent();
     17             random = new Random(DateTime.Now.Millisecond);
     18             penColor = GetRandomColor();
     19         }
     20 
     21         private Point GetRandomPoint()
     22         {
     23             return new Point(random.Next(0, ClientRectangle.Width), random.Next(0, ClientRectangle.Height - pnlToolbox.Height));
     24         }
     25 
     26         private Rectangle GetRandomRectangle()
     27         {
     28             var pointA = GetRandomPoint();
     29             var pointB = GetRandomPoint();
     30 
     31             return new Rectangle(Math.Min(pointA.X, pointB.X)
     32                 , Math.Min(pointA.Y, pointB.Y)
     33                 , Math.Abs(pointA.X - pointB.X)
     34                 , Math.Abs(pointA.Y - pointB.Y));
     35         }
     36 
     37         private Color GetRandomColor()
     38         {
     39             return Color.FromArgb(random.Next(0, 256), random.Next(0, 256), random.Next(0, 256));
     40         }
     41 
     42         private void ShowInformation(string message)
     43         {
     44             lblInformation.Text = message;
     45         }
     46 
     47         private void btnChangePenColor_Click(object sender, EventArgs e)
     48         {
     49             if (colors.ShowDialog(this) == DialogResult.OK)
     50             {
     51                 penColor = colors.Color;
     52             }
     53         }
     54 
     55         private void btnSwitchDoubleBuffered_Click(object sender, EventArgs e)
     56         {
     57             DoubleBuffered = !DoubleBuffered;
     58 
     59             ShowInformation($"二级缓冲:{DoubleBuffered}。");
     60         }
     61 
     62         private void btnDrawRandomEllipse_Click(object sender, EventArgs e)
     63         {
     64             var rectangle = GetRandomRectangle();
     65 
     66             var style = (DashStyle)(random.Next(0, 6));
     67             var dashCaps = new List<int> { 0, 2, 3 };
     68             var dashCap = (DashCap)dashCaps[random.Next(0, 3)];
     69 
     70             using (var g = CreateGraphics())
     71             using (var pen = new Pen(penColor, 4f))
     72             using (var brush = new LinearGradientBrush(rectangle, Color.Red, Color.Blue, LinearGradientMode.ForwardDiagonal))
     73             {
     74                 g.Clear(SystemColors.AppWorkspace);
     75                 g.SmoothingMode = SmoothingMode.HighQuality;
     76                 pen.DashStyle = style;
     77                 pen.DashCap = dashCap;
     78                 g.DrawEllipse(pen, rectangle);
     79             }
     80 
     81             ShowInformation($"随机椭圆,{rectangle},虚线冒:{dashCap.ToString()},线条样式:{style.ToString()}。");
     82         }
     83 
     84         private void btnDrawRandomCircle_Click(object sender, EventArgs e)
     85         {
     86             var rectangle = GetRandomRectangle();
     87             var diameter = Math.Min(rectangle.Size.Width, rectangle.Size.Height);
     88             rectangle = new Rectangle(rectangle.Location, new Size(diameter, diameter));
     89 
     90             var style = (DashStyle)(random.Next(0, 6));
     91             var dashCaps = new List<int> { 0, 2, 3 };
     92             var dashCap = (DashCap)dashCaps[random.Next(0, 3)];
     93 
     94             using (var g = CreateGraphics())
     95             using (var pen = new Pen(penColor, 4f))
     96             using (var brush = new LinearGradientBrush(rectangle, Color.Red, Color.Blue, LinearGradientMode.ForwardDiagonal))
     97             {
     98                 g.Clear(SystemColors.AppWorkspace);
     99                 g.SmoothingMode = SmoothingMode.HighQuality;
    100                 pen.DashStyle = style;
    101                 pen.DashCap = dashCap;
    102                 g.DrawEllipse(pen, rectangle);
    103             }
    104 
    105             ShowInformation($"正圆,{rectangle},虚线冒:{dashCap.ToString()},线条样式:{style.ToString()}。");
    106         }
    107 
    108         private void btnFillWithPathGradientBrush_Click(object sender, EventArgs e)
    109         {
    110             var rectangle = GetRandomRectangle();
    111 
    112             var wrapMode = (WrapMode)(random.Next(0, 5));
    113 
    114             //var points = new Point[] { GetRandomPoint(), GetRandomPoint(), GetRandomPoint(), GetRandomPoint(), GetRandomPoint() };
    115             var points = new Point[] { GetRandomPoint(), GetRandomPoint(), GetRandomPoint() };
    116 
    117             using (var g = CreateGraphics())
    118             using (var brush = new PathGradientBrush(points, wrapMode))
    119             {
    120                 g.Clear(SystemColors.AppWorkspace);
    121                 g.SmoothingMode = SmoothingMode.HighQuality;
    122                 g.DrawEllipse(Pens.LightGray, rectangle);
    123                 g.FillEllipse(brush, rectangle);
    124             }
    125 
    126             ShowInformation($"路径填充,{rectangle},WrapMode:{wrapMode}。");
    127         }
    128     }
    129 }
    画圆 —— FormDrawEllipses

    同样,一个窗体项目,窗体的布局风格与上一节的保持一致:

    几个方法不细说,直接上几个效果图草草了事……

    正圆就是一种特殊的椭圆,它的rectangle的宽与高相等;

    随机路径填充也蛮有意思的,有的图画,我都想直接拿来做logo了:)

    好了,画圆的部分,内容就这么多,按照惯例,那么我们就来利用现有的知识,再耍个花活,画个贼溜溜的眼珠:)

    private int maxDistance = 0;    // 最大移动距离,用来衡量鼠标距离眼球中心位置的极限;以这个距离极限,来等比缩放眼球移动的距离;
    private Rectangle leftEyeBorderRect = Rectangle.Empty   // 左眼眼眶
        , rightEyeBorderRect = Rectangle.Empty              // 右眼眼眶
        , leftEyeBackRect = Rectangle.Empty                 // 左眼兰眼球
        , rightEyeBackRect = Rectangle.Empty                // 右眼兰眼球
        , leftEyeFrontRect = Rectangle.Empty                // 左眼黑眼珠
        , rightEyeFrontRect = Rectangle.Empty;              // 右眼黑眼珠
    定义几个私有变量

    注释里说明了这几个变量的意义;

     1 private void btnDrawFollowMouseEyes_Click(object sender, EventArgs e)
     2 {
     3     var center = new Point(ClientRectangle.Width / 2, (ClientRectangle.Height - pnlToolbox.Height) / 2);
     4     leftEyeBorderRect = new Rectangle(center.X - 250, center.Y - 40, 200, 80);
     5     rightEyeBorderRect = new Rectangle(center.X + 50, center.Y - 40, 200, 80);
     6     maxDistance = ClientRectangle.Width < (ClientRectangle.Height - pnlToolbox.Height)
     7         ? center.X - 150 - ClientRectangle.X
     8         : center.Y - ClientRectangle.Y;
     9 
    10     var style = (DashStyle)(random.Next(0, 6));
    11     var dashCaps = new List<int> { 0, 2, 3 };
    12     var dashCap = (DashCap)dashCaps[random.Next(0, 3)];
    13 
    14     using (var g = CreateGraphics())
    15     using (var pen = new Pen(penColor, 2f))
    16     using (var brush = new SolidBrush(penColor))
    17     {
    18         g.Clear(SystemColors.AppWorkspace);
    19         g.SmoothingMode = SmoothingMode.HighQuality;
    20         pen.DashStyle = style;
    21         pen.DashCap = dashCap;
    22         g.FillEllipse(SystemBrushes.ControlLight, leftEyeBorderRect);
    23         g.DrawEllipse(pen, leftEyeBorderRect);
    24         g.FillEllipse(SystemBrushes.ControlLight, rightEyeBorderRect);
    25         g.DrawEllipse(pen, rightEyeBorderRect);
    26     }
    27 
    28     FormDrawEllipses_MouseMove(null, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0));
    29 
    30     ShowInformation($"贼溜溜的眼睛,跟随鼠标移动的眼睛示例。");
    31 }
    贼眼珠按钮事件 —— btnDrawFollowMouseEyes_Click

    这个事件中,主要就是画出眼眶和填充眼白;

     1 private void FormDrawEllipses_MouseMove(object sender, MouseEventArgs e)
     2 {
     3     if (Rectangle.Empty.Equals(leftEyeBorderRect) || Rectangle.Empty.Equals(rightEyeBorderRect))
     4         return;
     5 
     6     using (var g = CreateGraphics())
     7     using (var pen = new Pen(penColor, 2f))
     8     using (var brush = new SolidBrush(penColor))
     9     {
    10         if (Rectangle.Empty != leftEyeBackRect)
    11             g.FillEllipse(SystemBrushes.ControlLight, leftEyeBackRect);
    12         if (Rectangle.Empty != rightEyeBackRect)
    13             g.FillEllipse(SystemBrushes.ControlLight, rightEyeBackRect);
    14         leftEyeBackRect = CalcRect(leftEyeBorderRect, e.Location, maxDistance, 15, 25);
    15         rightEyeBackRect = CalcRect(rightEyeBorderRect, e.Location, maxDistance, 15, 25);
    16         leftEyeFrontRect = CalcRect(leftEyeBackRect, e.Location, maxDistance, 15, 5);
    17         rightEyeFrontRect = CalcRect(rightEyeBackRect, e.Location, maxDistance, 15, 5);
    18 
    19         brush.Color = Color.Blue;
    20         g.FillEllipse(brush, leftEyeBackRect);
    21         g.FillEllipse(brush, rightEyeBackRect);
    22 
    23         brush.Color = Color.Black;
    24         g.FillEllipse(brush, leftEyeFrontRect);
    25         g.FillEllipse(brush, rightEyeFrontRect);
    26 
    27         g.Flush();
    28     }
    29 }
    窗体的鼠标移动事件 —— FormDrawEllipses_MouseMove

    这个事件里,首先就是将上一次兰眼球的范围填充成眼白的颜色,然后就是根据当前鼠标位置,重新计算兰眼球和黑眼珠的位置,然后进行填充。

    这样就形成了一个动态效果了。

     1 private Rectangle CalcRect(Rectangle baseRect, Point mouseLocation, int maxDistance, int maxMoveDistance, int radius)
     2 {
     3     var baseCenter = Point.Add(baseRect.Location, new Size(baseRect.Width / 2, baseRect.Height / 2));
     4 
     5     var radian = Math.Atan2((mouseLocation.Y - baseCenter.Y), (mouseLocation.X - baseCenter.X));
     6 
     7     var mouseDistance = Math.Min(maxDistance, Math.Sqrt(Math.Pow(mouseLocation.X - baseCenter.X, 2) + Math.Pow(mouseLocation.Y - baseCenter.Y, 2)));
     8 
     9     var moveDistance = maxMoveDistance * (mouseDistance / maxDistance);
    10 
    11     var targetCenter = new Point((int)Math.Ceiling(moveDistance * Math.Cos(radian) + baseCenter.X), (int)Math.Ceiling(moveDistance * Math.Sin(radian)) + baseCenter.Y);
    12 
    13     return new Rectangle(targetCenter.X - radius, targetCenter.Y - radius, radius * 2, radius * 2);
    14 }
    辅助方法 —— 计算眼球和眼珠的矩形位置

    OK,完活,收工。


    喜欢本系列丛书的朋友,可以点击链接加入QQ交流群(994761602)【C# 破境之道】
    方便各位在有疑问的时候可以及时给我个反馈。同时,也算是给各位志同道合的朋友提供一个交流的平台。
    需要源码的童鞋,也可以在群文件中获取最新源代码。
  • 相关阅读:
    Random生成随机数
    Jmeter(八)Jmeter监控tomcat
    Jmeter(七)Mongodb的增删改查
    Jmeter(六)文件上传和下载文件
    Jmeter(五)mysql的增删改查
    Jmeter(四)测试webservice脚本
    Jmeter(三)断言和关联
    Jmeter(二)参数化
    Jmeter(一)http接口添加header和cookie
    Python学习笔记(一)数据类型
  • 原文地址:https://www.cnblogs.com/mikecheers/p/12343006.html
Copyright © 2011-2022 走看看