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

目录
  • 前言
    • 组件功能
  • 1、原理
  • 2、找点
  • 小结:

前言

开发中,免不了会用到多边形、多角星等图案,比较常用的多边形比如雷达图、多角星比如评价星级的五角星等,本篇文章就使用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多边形组件的资料请关注我们其它相关文章!

(0)

相关推荐

  • 详解利用Flutter中的Canvas绘制有趣的图形

    目录 简介 等边三角形构建重复之美 绘制彩虹 绘制五角星 总结 简介 上一篇我们介绍了使用 Flutter 的 Canvas 绘制基本图形的示例,简单的示例没什么好玩的,今天这一篇我们来点有趣的,我们会完成如下图形的绘制: 发现数学重复之美:使用等边三角形组合成彩虹伞面. 绘制彩虹. 绘制评分用的五角星. 通过这一篇,我们可以知道自定义形状绘制的基本原理,然后可以在这个基础上绘制你自己想要绘制的图形. 等边三角形构建重复之美 首先我们来绘制等边三角形,其实上一篇我们也有绘制等边三角形,只是那是将

  • 详解Flutter如何绘制曲线,折线图及波浪动效

    目录 正弦曲线绘制 波浪动效 曲线绘制 折线图 其他说明 总结 简介 上一篇用 Flutter 的 Canvas 画点有趣的图形我们介绍了使用 CustomPaint 绘制自定义形状,可以看到有了图形的平面绘制数学计算方法,我们可以画出所需的形状.本篇我们来介绍线条类图形的绘制,并且结合 Animation 实现了常见的波浪动效.通过本篇,你可以了解到: 正弦曲线的绘制 利用两条正弦曲线加上 Animation 实现波浪动效 曲线的一般绘制方法 折线图绘制 下面是最终实现的效果图,接下来我们一项

  • Android Flutter绘制扇形图详解

    目录 简介 CustomPaint介绍 CustomPainter介绍 paint介绍 shouldRepaint介绍 示例 使用CustomPaint 自定义Painter 绘制 触摸事件处理 动画实现 简介 在开发过程中通常会遇到一些不规则的UI,比如不规则的线条,多边形,统计图表等等,用那些通用组件通过组合的方式无法进行实现,这就需要我们自己进行绘制.可以通过使用CuntomPaint组件并结合画笔CustomPainter去进行手动绘制各种图形. CustomPaint介绍 Custom

  • Flutter利用Canvas绘制精美表盘效果详解

    目录 前言 初始化 面板 刻度 刻度线 刻度值 指针 时针 分针 秒针 动起来 前言 趁着周末空闲时间使用 Flutter 的 Canvas制作了一个精美表盘. 最终实现的效果还不错,如下: 前面说到使用 Canvas 实现该表盘效果,而在 Flutter 中使用 Canvas 更多的则是继承 CustomPainter 类实现 paint 方法,然后在 CustomPaint 中使用自定义实现的 CustomPainter. 比如这里创建的 DialPainter 使用如下: @overrid

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

    目录 前言 组件功能 1.原理 2.找点 小结: 前言 开发中,免不了会用到多边形.多角星等图案,比较常用的多边形比如雷达图.多角星比如评价星级的五角星等,本篇文章就使用Flutter绘制封装一个这样的组件. 组件功能 正多边形 正多角星 支持同时绘制多边形和多角星 角的饱满度调整 1.原理 五角星为例: 可以看到,在一个五角星中,一共有10个点,有5个点平均分布在大圆上面,有5个点平均分布在小圆上面,相当于对360度进行了10等分,那么我们只需要将这10个点找到,用线连起来即可. 2.找点 既

  • Python实现绘制多角星实例

    目录 一.引言 二.方法 三.实验结果与讨论 1.三角形的绘制 2.五角星的绘制 3.多角星的绘制 四. 结语 本文转自微信公众号:算法与编程之美 一.引言 在具备一定的Python编程基础以后,我们可以结合for循环进行多角星的编写,只要简单的几次循环,即可以极大的解决重复编写相同代码方面的问题,下面小编将以三角星.五角星为例,进而引入如何绘制多角星. 二.方法 预备知识: 命令 说明 pensize(width) 设置画笔宽度 turtle.forward(distance) 向画笔方向移动

  • 基于Flutter制作一个火箭发射动画

    目录 总结 前言 北京时间10月16日0时23分,神舟十三号飞船成功发射,目前三名航天员已经顺利进驻空间站,开始为期6个月的“太空差旅”生活. 国家的航天技术的突飞猛进也让岛上码农很自豪,今天看 Flutter 的动画知识,看到了 AnimatedPositioned 这个组件,可以用于控制组件的相对位置移动.结合这个神舟十三号的发射,灵机一动,正好可以使用AnimatedPositioned 这个组件实现火箭发射动画.话不多说,先上效果! 效果说明 这里其实是两张图片叠加,一张是背景地球星空的

  • 基于Flutter实现爱心三连动画效果

    目录 前言 Animation 简介 AnimationController 简介 应用 - 爱心三连 总结 前言 我们开始 Flutter 动画相关篇章之旅,在应用中通过动效能够给用户带来更愉悦的体验,比较典型的例子就是一些直播平台的动效了,比如送火箭能做出来那种火箭发射的动效——感觉倍有面子,当然这是土豪的享受,我等码农只在视频里看过.本篇我们来介绍基于 Animation 类实现的基本动画构建. Animation 简介 Animation 是一个抽象类,它并不参与屏幕的绘制,而是在设定的

  • 基于Flutter实现图片选择和图片上传

    目录 内容简介 图片选择插件 权限申请 UI 改造 图片上传 内容简介 本篇将介绍 Flutter 中如何完成图片上传,以及上传成功后的表单提交.涉及的知识点如下: 图片选择插件wechat_assets_picker的使用. 图片选择 iOS 和安卓的应用权限配置. 图片选择组件的封装. 图片上传接口的封装. 添加和编辑页面中图片上传实现. 图片选择插件 Flutter 的图片选择插件很多,包括了官方的 image_picker,multi_image_picker(基于2.0出了 multi

  • Android基于Flutter编写文件下载管理器

    目录 前言 Dio 的下载方法 download 监测下载进度 取消下载 删除已经下载的文件 调试过程中遇到的一些错误 运行结果及代码 总结 前言 文件下载在很多类型的应用中会涉及,例如音乐.文档.包括图片(只是图片可以使用一些组件完成无感知的下载).本篇介绍使用 Dio 的下载方法完成文件的下载,涉及到的内容如下: Dio 插件的 download 方法介绍: 使用 download 的回调方法监测下载进度: 使用 CancelToken 取消正在下载的任务: 删除已下载的文件: path_p

  • 基于Flutter制作一个吃豆人加载动画

    目录 效果图 绘制静态吃豆人.豆豆.眼睛 加入动画属性 总结 效果图 国际惯例,先看效果图: 具体效果就是吃豆人会根据吃不同颜色的豆子改变身体的颜色. 绘制静态吃豆人.豆豆.眼睛 首先,我们需要将这个静态的吃豆人绘制出来,我们可以把吃豆人看做是一个实心圆弧,豆豆和眼睛就是一个圆. 关键代码: //画头 _paint ..color = color.value ..style = PaintingStyle.fill; var rect = Rect.fromCenter( center: Off

  • 基于Flutter实现风车加载组件的制作

    目录 前言 接口定义 实现思路 风车绘制 旋转效果 代码实现 WindmillIndicator定义 旋转速度设定 风车叶片绘制 风车组件 运行效果 总结 前言 Flutter 官方提供了诸如 CircularProgressIndicator和 LinearProgressIndicator两种常见的加载指示组件,但是说实话,实在太普通,比如下面这个CircularProgressIndicator. 正好我们介绍到了动画环节,那我们自己来一个有趣的加载指示组件吧.创意送哪来呢,冥思苦想中脑海

  • 基于Flutter制作一个心碎动画特效

    目录 前言 实现步骤 1.绘制一个心 2.绘制心的裂痕 3.加入动画 完整代码 小结 前言 继续动画探索,今天用Flutter制作一个心碎的感觉,灵感来源于今天的股市,哎,心哇凉哇凉的.废话不多说,开始. 效果图先上: 实现步骤 1.绘制一个心 首先我们使用两段三阶贝塞尔曲线制作一个心型,这里因为需要实现心碎的效果,所以我们需要将心的两段用两段路径path进行绘制出来,效果: 绘制代码: canvas.translate(size.width / 2, size.height / 2); Pai

  • 基于Flutter实现转场动效的示例代码

    目录 前言 CupertinoFullscreenDialogTransition CupertinoPageTransition DecoratedBoxTransition FadeTransition PositionedTransition RotationTransition ScaleTransition SizeTransition SlideTransition 前言 动画经常会用于场景切换,比如滑动,缩放,尺寸变化,为应对这样的场景转换需要,Flutter 提供了 Transi

随机推荐