C#中GDI+绘制圆弧及圆角矩形等比缩放的绘制

作者:代码迷途 时间:2022-06-14 21:15:05 

理解圆弧绘制

GDI+中对于圆弧的绘制,是以给定的长方形(System.Drawing.Rectangle 结构)为边界绘制的椭圆的一部分形成的圆弧。绘制的圆弧的中心为长方形内切椭圆的圆心(如果是正方形,则正方形的中心是内切圆的圆心)

Graphics对象的DrawArc()方法用于绘制圆弧线段;GraphicsPath对象的AddArc()方法用于绘制圆弧路径。

DrawArc为例,参数为:DrawArc (System.Drawing.Pen pen, System.Drawing.Rectangle rect, float startAngle, float sweepAngle),绘制一段弧线,它表示 Rectangle 结构指定的椭圆的一部分。

  • pen 为画笔对象。

  • rect 包含圆弧的长方体结构。

  • startAngle 圆弧绘制的开始角度。

  • sweepAngle 从 startAngle 角度到弧线的结束点沿顺时针方向度量的角(以度为单位),即从startAngle开始绘制弧线转动的角度。

新建Winform项目GDIForArc,测试和演示弧形绘制的效果。

直接看下面的代码,分别绘制矩形对应的四个角的弧形(1/4圆),可以很直观的看到圆弧的绘制及与长方体的关系:

protected override void OnPaint(PaintEventArgs e)
{
   Graphics g = e.Graphics;
   Pen pn = new Pen(Color.Blue,5);
   Rectangle rect = new Rectangle(50, 50, 150, 150);
   g.DrawRectangle(pn, rect);

Rectangle rect2 = new Rectangle(300, 50, 150, 350);
   g.DrawRectangle(pn, rect2);

// 红色 0-90deg的圆弧
   pn.Color = RedColor;
   g.DrawArc(pn, rect, 0, 90);

g.DrawArc(pn, rect2, 0, 90);

// 黑色 90-180deg的圆弧
   pn.Color = BalckColor;
   g.DrawArc(pn, rect, 90, 90);

g.DrawArc(pn, rect2, 90, 90);

// 绿色 180-270deg的圆弧
   pn.Color = GreenColor;
   g.DrawArc(pn, rect, 180, 90);

g.DrawArc(pn, rect2, 180, 90);

// 粉色 270-360deg的圆弧
   pn.Color = HotPink;
   g.DrawArc(pn, rect, 270, 90);

g.DrawArc(pn, rect2, 270, 90);
}

C#中GDI+绘制圆弧及圆角矩形等比缩放的绘制

从圆弧到绘制圆角长方体

GDI+中绘图系统中顺时针方向为旋转正方向,水平向右方向为x轴正方向,垂直向下为y轴正方向。

通过Rectangle结构内的四个圆弧,可以组合成四个圆角,从而可以进一步实现圆角长方体、圆形等图形。

如下,是使用这个方式绘制的圆角矩形。

需要注意的点:

  • 线条连接时的1像素问题,很多时候会出现1像素的间隔,并没有完全闭合连接,需要额外处理

  • Pen.LineJoin 指定线条连接点的模式

// 绘制圆角矩形
pn.Color = Color.MediumVioletRed;
// 指定连接处的连接点
pn.LineJoin = LineJoin.Round;

Rectangle roundRect = new Rectangle(500, 50, 150, 80);
var radius = 20;
var R = radius * 2;
Rectangle arcRect = new Rectangle(roundRect.X, roundRect.Y, R, R);

// 左上角
g.DrawArc(pn, arcRect, 180, 90);
// 右上角
arcRect.X = roundRect.Right - R;
g.DrawArc(pn, arcRect, 270, 90);
// 右下角
arcRect.Y = roundRect.Bottom - R;
g.DrawArc(pn, arcRect, 0, 90);
// 左下角
arcRect.X = roundRect.Left;
g.DrawArc(pn, arcRect, 90, 90);

#region 单独绘制线条,需要处理1像素间隔问题,且连接处不平滑
g.DrawLine(pn, roundRect.X + radius, roundRect.Y, roundRect.Right - radius + 1, roundRect.Y);

g.DrawLine(pn, roundRect.Right, roundRect.Y + radius, roundRect.Right, roundRect.Bottom - radius + 1);

g.DrawLine(pn, roundRect.Right - radius + 1, roundRect.Bottom, roundRect.Left + radius, roundRect.Bottom);

g.DrawLine(pn, roundRect.Left, roundRect.Bottom - radius + 1, roundRect.Left, roundRect.Y + radius);
#endregion

C#中GDI+绘制圆弧及圆角矩形等比缩放的绘制

如何实现等比缩放绘制圆角矩形

按固定比例计算缩放矩形的尝试(不推荐)

根据上面绘制矩形的思路,想着同样实现一个按照等比缩放绘制内部圆角矩形的方式。主要思路是,指定一个缩放比例,让外部的矩形宽高、位置、圆角绘制的半径、直径等对应等比缩放并计算其值。

然后就是圆角矩形的绘制思路。

#region 等比缩放的绘制圆角矩形
//// 等比缩放,绘制内层圆角矩形
var scale = 0.8f;
var radiusScale = radius * scale;
var RScale = radiusScale * 2;
var innerRoundRect = new RectangleF(roundRect.X + (roundRect.Width - roundRect.Width * scale) / 2, roundRect.Y + (roundRect.Height - roundRect.Height * scale) / 2, roundRect.Width * scale, roundRect.Height * scale);
var arcRectScale = new RectangleF(innerRoundRect.X, innerRoundRect.Y, RScale, RScale);
//var scale = 0.8f;
//var radiusScale = Convert.ToInt32(radius * scale);
//var RScale = radiusScale * 2;
//var width = Convert.ToInt32(roundRect.Width * scale);
//var height = Convert.ToInt32(roundRect.Height * scale);
//var innerRoundRect = new Rectangle(roundRect.X + (roundRect.Width - width) / 2, roundRect.Y + (roundRect.Height - height) / 2, width, height);
//var arcRectScale = new Rectangle(innerRoundRect.X, innerRoundRect.Y, RScale, RScale);

pn.Color = Color.MediumPurple;
arcRectScale.X = innerRoundRect.X;
arcRectScale.Y = innerRoundRect.Y;

// 左上角
g.DrawArc(pn, arcRectScale, 180, 90);
g.DrawLine(pn, innerRoundRect.X + radiusScale, innerRoundRect.Y, innerRoundRect.Right - radiusScale + 1, innerRoundRect.Y);
// 右上角
arcRectScale.X = innerRoundRect.Right - RScale;
g.DrawArc(pn, arcRectScale, 270, 90);
g.DrawLine(pn, innerRoundRect.Right, innerRoundRect.Y + radiusScale, innerRoundRect.Right, innerRoundRect.Bottom - radiusScale + 1);
// 右下角
arcRectScale.Y = innerRoundRect.Bottom - RScale;
g.DrawArc(pn, arcRectScale, 0, 90);
g.DrawLine(pn, innerRoundRect.Right - radiusScale + 1, innerRoundRect.Bottom, innerRoundRect.Left + radiusScale, innerRoundRect.Bottom);
// 左下角
arcRectScale.X = innerRoundRect.Left;
g.DrawArc(pn, arcRectScale, 90, 90);
g.DrawLine(pn, innerRoundRect.Left, innerRoundRect.Bottom - radiusScale + 1, innerRoundRect.Left, innerRoundRect.Y + radiusScale);
#endregion

去掉外层圆角矩形的直线,效果如下:

C#中GDI+绘制圆弧及圆角矩形等比缩放的绘制

直接计算比例的问题在于,由于矩形长宽大小的不同,计算出来内部(或外部)矩形的缩小或增大的量会不同,原则上,应该是长宽方向上缩小固定的量(类似边框在长宽方向时,边框的大小都是一样的)。因此,最好取其中一个值。

缩小或增大的矩形的圆角半径是否应该对应缩放?这是一直没有很好处理的问题,如果缩小放大的变化不大,则没有太大区别,如果比较大,圆角半径最好保持不变(上例代码为圆角半径也跟着缩放的例子)

通过Inflate()方法缩放矩形

Inflate()可分为实例方法和静态方法,它是专门用于缩放矩形的长宽指定的量的方法,而不是长宽不对等的比例计算。

推荐使用它加上圆角半径不变的方式,计算内层或外层圆角矩形。

Inflate的使用代码如下,其他不变的代码部分不再列出。

var inflateRect = Rectangle.Inflate(roundRect, -8, -8);
// inflateRect.Inflate(-8, -8); // 实例方法,长宽缩小或放大指定的量,改变的实例本身

// others

来源:https://juejin.cn/post/7136952741041012750

标签:C#,GDI,绘制,圆弧
0
投稿

猜你喜欢

  • 基于rocketmq的有序消费模式和并发消费模式的区别说明

    2021-10-29 08:41:02
  • Entity Framework使用ObjectContext类

    2023-01-25 16:40:04
  • window下安装和配置maven环境

    2021-06-13 14:32:16
  • Mybatis Limit实现分页功能

    2022-03-14 13:57:57
  • 聊聊Spring AOP @Before @Around @After等advice的执行顺序

    2022-10-27 18:14:20
  • Java通过HttpClient进行HTTP请求的代码详解

    2022-06-04 09:50:20
  • Gradle:修改默认的Build配置文件名方式

    2023-11-28 20:18:01
  • SpringMvc微信支付回调示例代码

    2023-01-24 08:00:03
  • 带大家认识Java语法之泛型与通配符

    2021-06-04 06:14:46
  • java算法题解牛客BM99顺时针旋转矩阵示例

    2021-07-08 18:55:18
  • IDEA 2019.1.3 激活码大全

    2023-05-09 05:20:37
  • java编写的文件管理器代码分享

    2023-11-20 13:28:52
  • 浅谈用java实现事件驱动机制

    2022-07-12 18:06:03
  • android实现图片橡皮擦和快速染色功能

    2023-09-08 01:30:02
  • SpringBoot+Dubbo+Zookeeper实现简单分布式开发的应用详解

    2022-03-02 00:47:40
  • 用Java程序判断是否是闰年的简单实例

    2022-10-13 23:04:30
  • dubbo入门指南及demo实例详解

    2023-08-24 04:49:07
  • mybatis查询返回Map<String,Object>类型的讲解

    2022-12-25 02:07:38
  • SpringBoot之Helloword 快速搭建一个web项目(图文)

    2023-08-23 17:36:21
  • java 输入一个数字组成的数组(输出该数组的最大值和最小值)

    2023-11-24 21:41:58
  • asp之家 软件编程 m.aspxhome.com