網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
前言
開(kāi)發(fā)中,免不了會(huì)用到多邊形、多角星等圖案,比較常用的多邊形比如雷達(dá)圖、多角星比如評(píng)價(jià)星級(jí)的五角星等,本篇文章就使用Flutter繪制封裝一個(gè)這樣的組件。
組件功能
- 正多邊形
- 正多角星
- 支持同時(shí)繪制多邊形和多角星
- 角的飽滿度調(diào)整
1、原理
五角星為例:
可以看到,在一個(gè)五角星中,一共有10
個(gè)點(diǎn),有5
個(gè)點(diǎn)平均分布在大圓上面,有5
個(gè)點(diǎn)平均分布在小圓上面,相當(dāng)于對(duì)360度進(jìn)行了10
等分,那么我們只需要將這10
個(gè)點(diǎn)找到,用線連起來(lái)即可。
2、找點(diǎn)
既然知道了點(diǎn)的分布規(guī)律,我們只需要拿到圓的半徑通過(guò)三角函數(shù)就能得到每個(gè)點(diǎn)的坐標(biāo),通過(guò)path路徑進(jìn)行連接即可。
// 大圓半徑 double r = bigR ?? size.width / 2 / 2; // 小圓半徑 double r2 = smallR ?? size.width / 2 / 2 - 12; Path path = Path(); // 設(shè)置起點(diǎn) path.moveTo(r * cos(pi / count), r * sin(pi / count)); // 將圓等分 count = 角的個(gè)數(shù) /// 繪制角 for (int i = 2; i <= count * 2; i++) { if (i.isEven) { path.lineTo(r2 * cos(pi / count * i), r2 * sin(pi / count * i)); } else { path.lineTo(r * cos(pi / count * i), r * sin(pi / count * i)); } } // 閉合 path.close(); canvas.drawPath(path, paint2); // 繪制輔助線 path.reset(); for (int i = 1; i <= count * 2; i++) { if (i.isEven) { path.reset(); path.lineTo(r2 * cos(pi / count * i), r2 * sin(pi / count * i)); canvas.drawPath(path, paint2..color = Colors.redAccent); } else { path.reset(); path.lineTo(r * cos(pi / count * i), r * sin(pi / count * i)); canvas.drawPath(path, paint2..color = Colors.blue); } }
默認(rèn)效果是這樣的,
畫(huà)布默認(rèn)0度是X軸右移方向,如果需要將一個(gè)角朝著正上,這里需要將畫(huà)布進(jìn)行旋轉(zhuǎn)一定角度,將0度改為Y軸向上方面,然后再偏移一定角度即可。
//旋轉(zhuǎn)角度讓尖角朝上 canvas.rotate(pi / 2 * 3 + pi / count);
角的點(diǎn)找到了,那么多邊形就直接連接大圓上的角就行了,就很簡(jiǎn)單。
角的飽滿度通過(guò)修改小圓半徑即可。
最終效果圖:
源碼:
enum Type { angle, // 角 side, // 邊 all, // 都有 } /// 角 邊 型 class Polygonal extends StatelessWidget { final double size; // 組件大小 final double? bigR; // 大圓半徑 final double? smallR; // 小圓半徑 final int count; // 幾邊形 final Type type; // 五角星or五邊形 final bool isFill; // 是否填充 final Color color; // 顏色 const Polygonal( {Key? key, this.size = 80, this.bigR, this.smallR, this.count = 3, this.type = Type.angle, this.isFill = false, this.color = Colors.black87}) : super(key: key); @override Widget build(BuildContext context) { return CustomPaint( size: Size(size, size), painter: _PolygonalPainter(bigR, smallR, color: color, count: count, type: type, isFill: isFill), ); } } class _PolygonalPainter extends CustomPainter { final double? bigR; final double? smallR; final int count; // 幾邊形 final Type type; // 五角星or五邊形 final bool isFill; // 是否填充 final Color color; // 顏色 _PolygonalPainter(this.bigR, this.smallR, {required this.count, required this.type, required this.isFill, required this.color}); @override void paint(Canvas canvas, Size size) { canvas.clipRect(Offset.zero & size); canvas.translate(size.width / 2, size.height / 2); Paint paint2 = Paint() ..color = color ..strokeJoin = StrokeJoin.round ..style = isFill ? PaintingStyle.fill : PaintingStyle.stroke ..strokeWidth = 2; double r = bigR ?? size.width / 2 / 2; double r2 = smallR ?? size.width / 2 / 2 - 12; // 將圓等分 Path path = Path(); canvas.rotate(pi / count + pi / 2 * 3); path.moveTo(r * cos(pi / count), r * sin(pi / count)); /// 繪制角 if (type == Type.angle || type == Type.all) { for (int i = 2; i <= count * 2; i++) { if (i.isEven) { path.lineTo(r2 * cos(pi / count * i), r2 * sin(pi / count * i)); } else { path.lineTo(r * cos(pi / count * i), r * sin(pi / count * i)); } } path.close(); canvas.drawPath(path, paint2); } /// 繪制邊 if (type == Type.side || type == Type.all) { path.reset(); path.moveTo(r * cos(pi / count), r * sin(pi / count)); for (int i = 2; i <= count * 2; i++) { if (i.isOdd) { path.lineTo(r * cos(pi / count * i), r * sin(pi / count * i)); } } path.close(); canvas.drawPath(path, paint2); } } @override bool shouldRepaint(covariant CustomPainter oldDelegate) { return false; } }
小結(jié):
圓其實(shí)可以理解為一個(gè)無(wú)限邊的正多邊形,這也印證了世上沒(méi)有完美的圓。因?yàn)檫吺菬o(wú)限的,通過(guò)本篇我們利用圓的輔助繪制了多邊形以及多角星,希望對(duì)大家有所幫助 ~
原文鏈接:https://juejin.cn/post/7101620538790903816
相關(guān)推薦
- 2022-06-21 C++超詳細(xì)講解友元的使用_C 語(yǔ)言
- 2022-02-13 Flutter在showModalBottomSheet中使用StatefulWidget
- 2022-07-21 數(shù)據(jù)庫(kù)表數(shù)據(jù)操作-新增、刪除、修改
- 2022-03-25 C語(yǔ)言設(shè)計(jì)模式之命令模式介紹_C 語(yǔ)言
- 2022-06-12 C語(yǔ)言實(shí)題講解快速掌握單鏈表上_C 語(yǔ)言
- 2022-03-22 詳解_beginthreadex()創(chuàng)建線程_C 語(yǔ)言
- 2022-05-10 設(shè)備像素比devicePixelRatio
- 2023-10-14 WIN32 預(yù)定義宏WIN32,_WIN32,_WIN64介紹使用
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支