软件编程
位置:首页>> 软件编程>> flutter编程>> 基于Flutter实现多边形和多角星组件

基于Flutter实现多边形和多角星组件

作者:老李code  发布时间:2023-06-19 06:02:50 

标签:Flutter,多边形,多角星,组件

前言

开发中,免不了会用到多边形、多角星等图案,比较常用的多边形比如雷达图、多角星比如评价星级的五角星等,本篇文章就使用Flutter绘制封装一个这样的组件。

组件功能

  • 正多边形

  • 正多角星

  • 支持同时绘制多边形和多角星

  • 角的饱满度调整

1、原理

五角星为例:

基于Flutter实现多边形和多角星组件

可以看到,在一个五角星中,一共有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);
 }
}

默认效果是这样的,

基于Flutter实现多边形和多角星组件

画布默认0度是X轴右移方向,如果需要将一个角朝着正上,这里需要将画布进行旋转一定角度,将0度改为Y轴向上方面,然后再偏移一定角度即可。

//旋转角度让尖角朝上
canvas.rotate(pi / 2 * 3 + pi / count);

角的点找到了,那么多边形就直接连接大圆上的角就行了,就很简单。

角的饱满度通过修改小圆半径即可。

最终效果图:

基于Flutter实现多边形和多角星组件

源码:

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;
 }
}

小结:

圆其实可以理解为一个无限边的正多边形,这也印证了世上没有完美的圆。因为边是无限的,通过本篇我们利用圆的辅助绘制了多边形以及多角星,希望对大家有所帮助 ~

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

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com