網(wǎng)站首頁 編程語言 正文
理解圓弧繪制
GDI+中對于圓弧的繪制,是以給定的長方形(System.Drawing.Rectangle
?結(jié)構(gòu))為邊界繪制的橢圓的一部分形成的圓弧。繪制的圓弧的中心為長方形內(nèi)切橢圓的圓心(如果是正方形,則正方形的中心是內(nèi)切圓的圓心)
Graphics
對象的DrawArc()
方法用于繪制圓弧線段;GraphicsPath
對象的AddArc()
方法用于繪制圓弧路徑。
以DrawArc
為例,參數(shù)為:DrawArc (System.Drawing.Pen pen, System.Drawing.Rectangle rect, float startAngle, float sweepAngle)
,繪制一段弧線,它表示 Rectangle 結(jié)構(gòu)指定的橢圓的一部分。
- pen 為畫筆對象。
- rect 包含圓弧的長方體結(jié)構(gòu)。
- startAngle 圓弧繪制的開始角度。
- sweepAngle 從 startAngle 角度到弧線的結(jié)束點沿順時針方向度量的角(以度為單位),即從startAngle開始繪制弧線轉(zhuǎn)動的角度。
新建Winform項目GDIForArc
,測試和演示弧形繪制的效果。
直接看下面的代碼,分別繪制矩形對應(yīng)的四個角的弧形(1/4圓),可以很直觀的看到圓弧的繪制及與長方體的關(guān)系:
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); }
從圓弧到繪制圓角長方體
GDI+中繪圖系統(tǒng)中順時針方向為旋轉(zhuǎn)正方向,水平向右方向為x軸正方向,垂直向下為y軸正方向。
通過Rectangle結(jié)構(gòu)內(nèi)的四個圓弧,可以組合成四個圓角,從而可以進一步實現(xiàn)圓角長方體、圓形等圖形。
如下,是使用這個方式繪制的圓角矩形。
需要注意的點:
- 線條連接時的1像素問題,很多時候會出現(xiàn)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
如何實現(xiàn)等比縮放繪制圓角矩形
按固定比例計算縮放矩形的嘗試(不推薦)
根據(jù)上面繪制矩形的思路,想著同樣實現(xiàn)一個按照等比縮放繪制內(nèi)部圓角矩形的方式。主要思路是,指定一個縮放比例,讓外部的矩形寬高、位置、圓角繪制的半徑、直徑等對應(yīng)等比縮放并計算其值。
然后就是圓角矩形的繪制思路。
#region 等比縮放的繪制圓角矩形 //// 等比縮放,繪制內(nèi)層圓角矩形 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
去掉外層圓角矩形的直線,效果如下:
直接計算比例的問題在于,由于矩形長寬大小的不同,計算出來內(nèi)部(或外部)矩形的縮小或增大的量會不同,原則上,應(yīng)該是長寬方向上縮小固定的量(類似邊框在長寬方向時,邊框的大小都是一樣的)。因此,最好取其中一個值。
縮小或增大的矩形的圓角半徑是否應(yīng)該對應(yīng)縮放?這是一直沒有很好處理的問題,如果縮小放大的變化不大,則沒有太大區(qū)別,如果比較大,圓角半徑最好保持不變(上例代碼為圓角半徑也跟著縮放的例子)
通過Inflate()方法縮放矩形
Inflate()
可分為實例方法和靜態(tài)方法,它是專門用于縮放矩形的長寬指定的量的方法,而不是長寬不對等的比例計算。
推薦使用它加上圓角半徑不變的方式,計算內(nèi)層或外層圓角矩形。
Inflate的使用代碼如下,其他不變的代碼部分不再列出。
var inflateRect = Rectangle.Inflate(roundRect, -8, -8); // inflateRect.Inflate(-8, -8); // 實例方法,長寬縮小或放大指定的量,改變的實例本身 // others
原文鏈接:https://juejin.cn/post/7136952741041012750
相關(guān)推薦
- 2022-04-21 新一代Python包管理工具_python
- 2022-06-13 詳解Python如何利用Pandas與NumPy進行數(shù)據(jù)清洗_python
- 2022-04-16 python?import模塊時有錯誤紅線的原因_python
- 2023-07-07 JdbcTemplate基本使用
- 2022-06-12 python下grpc與protobuf的編寫使用示例_python
- 2022-05-31 C++核心編程之內(nèi)存分區(qū)詳解_C 語言
- 2022-07-13 redis搭建哨兵集群的實現(xiàn)步驟_Redis
- 2022-11-14 React前端路由應(yīng)用介紹_React
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支