基于Flutter实现多边形和多角星组件
前言
开发中,免不了会用到多边形、多角星等图案,比较常用的多边形比如雷达图、多角星比如评价星级的五角星等,本篇文章就使用Flutter绘制封装一个这样的组件。
组件功能
- 正多边形
- 正多角星
- 支持同时绘制多边形和多角星
- 角的饱满度调整
1、原理
五角星为例:
可以看到,在一个五角星中,一共有10
个点,有5
个点平均分布在大圆上面,有5
个点平均分布在小圆上面,相当于对360度进行了10
等分,那么我们只需要将这10
个点找到,用线连起来即可。
2、找点
既然知道了点的分布规律,我们只需要拿到圆的半径通过三角函数就能得到每个点的坐标,通过path路径进行连接即可。
// 大圆半径 double r = bigR ?? size.width / 2 / 2; // 小圆半径 double r2 = smallR ?? size.width / 2 / 2 - 12; Path path = Path(); // 设置起点 path.moveTo(r * cos(pi / count), r * sin(pi / count)); // 将圆等分 count = 角的个数 /// 绘制角 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); } }
默认效果是这样的,
画布默认0度是X轴右移方向,如果需要将一个角朝着正上,这里需要将画布进行旋转一定角度,将0度改为Y轴向上方面,然后再偏移一定角度即可。
//旋转角度让尖角朝上 canvas.rotate(pi / 2 * 3 + pi / count);
角的点找到了,那么多边形就直接连接大圆上的角就行了,就很简单。
角的饱满度通过修改小圆半径即可。
最终效果图:
源码:
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; } }
小结:
圆其实可以理解为一个无限边的正多边形,这也印证了世上没有完美的圆。因为边是无限的,通过本篇我们利用圆的辅助绘制了多边形以及多角星,希望对大家有所帮助 ~
以上就是基于Flutter实现多边形和多角星组件的详细内容,更多关于Flutter多边形组件的资料请关注脚本之家其它相关文章!
相关文章
微信小程序—微信跳一跳,Android游戏助手(外挂)使用教程详解
这篇文章主要介绍了微信小程序—微信跳一跳,Android游戏助手(外挂)使用教程详解,需要的朋友可以参考下2018-01-01内存泄露导致Android 中setVisibility() 失效原理
这篇文章主要介绍了内存泄露导致Android 中setVisibility() 失效原理,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感兴趣的小伙伴可以参考一下2022-07-07Android WebView交互传递json字符串并解析的方法
这篇文章主要给大家介绍了关于Android中WebView交互传递json字符串并解析的相关资料,文中通过示例代码介绍的非常详细,对各位Android开发者具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。2018-05-05Android使用CrashHandler来获取应用的crash信息的方法
本篇文章主要介绍了Android使用CrashHandler来获取应用的crash信息的方法,具有一定的参考价值,有兴趣的可以了解一下2017-09-09Android 通过代码设置、打开wifi热点及热点连接的实现代码
这篇文章主要介绍了Android 通过代码设置、打开wifi热点及热点连接的实现代码,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下2018-05-05Android notifyDataSetChanged() 动态更新ListView案例详解
这篇文章主要介绍了Android notifyDataSetChanged() 动态更新ListView案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下2021-08-08
最新评论