基于Flutter实现多边形和多角星组件
作者:老李code 发布时间:2023-06-19 06:02:50
标签: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;
}
}
小结:
圆其实可以理解为一个无限边的正多边形,这也印证了世上没有完美的圆。因为边是无限的,通过本篇我们利用圆的辅助绘制了多边形以及多角星,希望对大家有所帮助 ~
来源:https://juejin.cn/post/7101620538790903816
![](https://www.aspxhome.com/images/zang.png)
![](https://www.aspxhome.com/images/jiucuo.png)
猜你喜欢
- 在Thread中注入Bean无效在Spring项目中,有时需要新开线程完成一些复杂任务,而线程中可能需要注入一些服务。而通过Spring注入
- 一、前言在mybatis官网中,有插件一说 mybatis plugins 如果同时有多个插件,那么他们的执行顺序是怎样的?二、准备工作、代
- 美团外卖菜单界面的Android实现代码,供大家参考,具体内容如下布局文件总布局<?xml version="1.0&quo
- 在封装中有一种特殊的类,能够把基本的数据类型进行转换来方便实际的使用。我们在之前提到的一些数据类型,最明显的特征是所有字母为小写状态,那么经
- 平时开发的工作中, 自己组内的很多大佬经常使用Optional的用法, 自己问他们, 这个到底有什么好处呢,他们说可以很好的规避好空指针的问
- 本文介绍了SpringBoot结合SpringSecurity实现图形验证码功能,分享给大家,具体如下:生成图形验证码根据随机数生成图片将随
- C语言字符串大小比较#include <stdio.h>#include <string.h>int fun(cha
- 本文主要介绍Android实现拍照、录像、录音代码的资料,这里整理了详细的代码,有需要的小伙伴可以参考下。RecordActivity.ja
- 我们都知道可以用爬虫来找寻一些想要的数据,除了可以使用python进行操作,我们最近学习的java同样也支持爬虫的运行,本篇小编就教大家用j
- 本文实例讲述了Java解析Excel内容的方法。分享给大家供大家参考。具体实现方法如下:import java.io.File;
- 我们经常会将数据源放在DataTable里面,但是有时候也需要移除不想要的行,下面的代码告诉你们DataTable dts;DataRow[
- 情况简介spring项目,controller异步调用service的方法,产生大量并发。具体业务:前台同时传入大量待翻译的单词,后台业务接
- package com.test; import java.io.BufferedReader; import jav
- 本文实例分析了C#中var关键字用法。分享给大家供大家参考。具体方法如下:C#关键字是伴随着.NET 3.5以后,伴随着匿名函数、LINQ而
- 本文实例讲述了Java连接redis及基本操作。分享给大家供大家参考,具体如下:点击此处:本站下载安装。解压安装启动redis:使用cd命令
- 本文实例讲述了Android编程实现的短信编辑器功能。分享给大家供大家参考,具体如下:修改短信数据库,从而生成任意手机号发送的短信。Andr
- 实践过程效果代码public partial class Form1 : Form{ public Form1()
- class文件中的常量池之前我们在讲class文件的结构时,提到了每个class文件都有一个常量池,常量池中存了些什么东西呢?字符串常量,类
- List list=new ArrayList()是怎么回事首先明确List是接口,ArrayList是它的实现类以下两种方法都可以,但是不
- 一、Flutter代码的启动起点我们在多数的业务场景下,使用的都是FlutterActivity、FlutterFragment。在在背后,