123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- import 'dart:math';
- import 'dart:math' as math;
- import 'dart:ui' as ui;
- import 'dart:ui';
- import 'package:flutter/material.dart';
- class OnePage extends StatefulWidget {
- @override
- OnePageState createState() => new OnePageState();
- }
- class OnePageState extends State<OnePage> {
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- backgroundColor: Color(0xFF3B62EE),
- appBar: AppBar(
- title: Text(''),
- ),
- body: Center(
- child: radarMapComponent(
- ["观察能力", "迁移发散能力", "归纳总结能力", "分类比较能力", "描述记录能力", "质疑猜想能力"],
- // ["观察能力", "迁移发散能力", "归纳总结能力", "分类比较能力",],
- 30.0,
- 18.0,
- context: context,
- ),
- ),
- );
- }
- @override
- void initState() {
- // TODO: implement initState
- super.initState();
- }
- }
- /// titlesList:外面的标题数组
- /// minRadius:最小圆的半径
- /// poorRadius:扩散圆的半径差
- Widget radarMapComponent(
- List titlesList,
- double minRadius,
- double poorRadius, {
- required BuildContext context,
- }) {
- double maxRadius = minRadius + poorRadius * titlesList.length - 1;
- return Container(
- width: maxRadius * 2 + 100,
- height: maxRadius * 2 + 100,
- child: CustomPaint(
- size: Size(maxRadius * 2 + 100, maxRadius * 2 + 100),
- painter: TolyPainter(
- titlesList: titlesList,
- minRadius: minRadius,
- poorRadius: poorRadius,
- context: context)),
- );
- }
- class TolyPainter extends CustomPainter {
- final BuildContext context;
- final List titlesList;
- final double minRadius;
- final double poorRadius;
- TolyPainter({
- required this.context,
- required this.titlesList,
- required this.minRadius,
- required this.poorRadius,
- });
- @override
- void paint(Canvas canvas, Size size) {
- double maxRadius = minRadius + poorRadius * (titlesList.length - 1);
- canvas.translate(size.width / 2, size.height / 2);
- //虚线画笔
- Paint dottedLinePaint = Paint()
- ..style = PaintingStyle.stroke
- ..color = Color(0xFFB9BEE6)
- ..strokeWidth = 1;
- Paint paint = Paint()
- ..style = PaintingStyle.stroke
- ..color = Color(0xFFE5E3FD)
- ..strokeWidth = 1;
- //多边形画笔
- Paint polygonBrushesPaint = Paint()
- ..style = PaintingStyle.fill
- ..color = Color(0xFFF6A5AB).withOpacity(0.52)
- ..strokeWidth = 1;
- Paint polygonBrushesPaint1 = Paint()
- ..style = PaintingStyle.stroke
- ..color = Color(0xFFF6A5AB)
- ..strokeWidth = 1;
- Path polygonBrushesPath = Path();
- //文字画笔
- TextPainter _textPainter = new TextPainter(
- textAlign: TextAlign.left, textDirection: TextDirection.ltr);
- final Path path = Path();
- final dottedLinePath = Path();
- //绘制文字
- for (int i = 0; i < titlesList.length; i++) {
- Size textSize = boundingTextSize(
- context, titlesList[i], TextStyle(color: Colors.white, fontSize: 9));
- canvas.save(); //与restore配合使用保存当前画布
- canvas.translate(0.0, -maxRadius - 10); //平移画布画点于时钟的12点位置,+30为了调整数字与刻度的间隔
- _textPainter.text = TextSpan(
- style: TextStyle(color: Colors.white, fontSize: 9),
- text: titlesList[i]);
- canvas.rotate(-angleToRadian(360 / titlesList.length * i)); //保持画的文字竖直显示。
- _textPainter.layout();
- //
- double radiu = 360 / titlesList.length * i;
- if (radiu == 0 || radiu == 1) {
- _textPainter.paint(canvas,
- Offset(-_textPainter.width / 2, -_textPainter.height / 2 - 5));
- } else if (0 < radiu && radiu < 180) {
- _textPainter.paint(canvas, Offset(0, -5));
- } else if (180 < radiu && radiu < 360) {
- _textPainter.paint(canvas, Offset(-_textPainter.width, -5));
- } else {
- _textPainter.paint(canvas,
- Offset(-_textPainter.width / 2, -_textPainter.height / 2 + 5));
- }
- canvas.restore(); //画布重置,恢复到控件中心
- canvas.rotate(
- angleToRadian(360 / titlesList.length)); //画布旋转一个区间刻度,把文字和刻度对应起来
- }
- List<Offset> pointsList = [];
- for (int i = 0; i < titlesList.length; i++) {
- path.moveTo(0, 0);
- dottedLinePath.moveTo(0, 0);
- if (i < titlesList.length - 1) {
- dottedLinePath.addOval(
- Rect.fromCircle(center: Offset.zero, radius: 30.0 + 18 * i));
- }
- double maxRadius = minRadius + poorRadius * titlesList.length;
- double x = (30 + 18 * (titlesList.length - 1)) *
- cos(angleToRadian(360 / titlesList.length * (i + 1) - 90));
- double y = (30 + 18 * (titlesList.length - 1)) *
- sin(angleToRadian(360 / titlesList.length * (i + 1) - 90));
- path.lineTo(x, y);
- pointsList.add(Offset(
- cos(angleToRadian(360 / titlesList.length * (i + 1) - 90)) *
- maxRadius *
- (i + 1 > titlesList.length - 1 ? titlesList.length - 2 : i + 1) /
- titlesList.length,
- sin(angleToRadian(360 / titlesList.length * (i + 1) - 90)) *
- maxRadius *
- (i + 1 > titlesList.length - 1 ? titlesList.length - 1 : i + 1) /
- titlesList.length));
- }
- polygonBrushesPath.addPolygon(pointsList, true);
- canvas.drawPath(polygonBrushesPath, polygonBrushesPaint);
- canvas.drawPath(polygonBrushesPath, polygonBrushesPaint1);
- for (int i = 0; i < titlesList.length; i++) {
- ParagraphBuilder pb = ParagraphBuilder(ParagraphStyle(
- textAlign: TextAlign.left,
- fontWeight: FontWeight.w600,
- fontStyle: FontStyle.normal,
- fontSize: 7,
- ))
- ..pushStyle(ui.TextStyle(color: Color(0xFFB9BEE6)))
- ..addText((i * 2).toString());
- ParagraphConstraints pc = ParagraphConstraints(width: 50);
- Paragraph paragraph = pb.build()..layout(pc);
- canvas.drawParagraph(
- paragraph,
- Offset(
- (minRadius + poorRadius * i) *
- (11 + 13 * i) /
- (minRadius + poorRadius * i),
- (minRadius + poorRadius * i) *
- (11 + 13 * i) /
- (minRadius + poorRadius * i)));
- }
- DashPainter(span: 4, step: 9, pointWidth: 10)
- .paint(canvas, dottedLinePath, dottedLinePaint);
- canvas.drawPath(path, paint);
- canvas.drawCircle(
- Offset.zero, minRadius + 18 * (titlesList.length - 1), paint);
- ParagraphBuilder pb = ParagraphBuilder(ParagraphStyle(
- textAlign: TextAlign.left,
- fontWeight: FontWeight.w600,
- fontStyle: FontStyle.normal,
- fontSize: 7,
- ))
- ..pushStyle(ui.TextStyle(color: Color(0xFFB9BEE6)))
- ..addText((titlesList.length * 2).toString());
- ParagraphConstraints pc = ParagraphConstraints(width: 50);
- Paragraph paragraph = pb.build()..layout(pc);
- canvas.drawParagraph(
- paragraph,
- Offset(
- (minRadius + poorRadius * titlesList.length) *
- (11 + 13 * titlesList.length) /
- (minRadius + poorRadius * titlesList.length),
- (minRadius + poorRadius * titlesList.length) *
- (11 + 13 * titlesList.length) /
- (minRadius + poorRadius * titlesList.length)));
- }
- static Size boundingTextSize(
- BuildContext context, String text, TextStyle style,
- {int maxLines = 2 ^ 31, double maxWidth = double.infinity}) {
- if (text == null || text.isEmpty) {
- return Size.zero;
- }
- final TextPainter textPainter = TextPainter(
- textDirection: TextDirection.ltr,
- locale: Localizations.maybeLocaleOf(context),
- text: TextSpan(text: text, style: style),
- maxLines: maxLines)
- ..layout(maxWidth: maxWidth);
- return textPainter.size;
- }
- ///角度换算成弧度 参数[angle]为角度
- static double angleToRadian(double angle) {
- return angle * pi / 180;
- }
- @override
- bool shouldRepaint(covariant TolyPainter oldDelegate) => false;
- }
- class DashPainter {
- const DashPainter({
- this.step = 2,
- this.span = 2,
- this.pointCount = 0,
- required this.pointWidth,
- });
- final double step; //实现的长度
- final double span; //虚线的长度
- final int pointCount; //点划线数
- final double pointWidth; //点划线长
- void paint(Canvas canvas, Path path, Paint paint) {
- final PathMetrics pms =
- path.computeMetrics(); //为此路径创建一个PathMetrics对象,该对象可以描述有关路径轮廓的各种属性。
- final double pointLineLength = pointWidth;
- final double partLength =
- step + span * (pointCount + 1) + pointCount * pointLineLength;
- pms.forEach((PathMetric pm) {
- final int count = pm.length ~/ partLength;
- for (int i = 0; i < count; i++) {
- canvas.drawPath(
- pm.extractPath(partLength * i, partLength * i + step),
- paint,
- );
- for (int j = 1; j <= pointCount; j++) {
- final start =
- partLength * i + step + span * j + pointLineLength * (j - 1);
- canvas.drawPath(
- pm.extractPath(start, start + pointLineLength),
- paint,
- );
- }
- }
- final double tail = pm.length % partLength;
- canvas.drawPath(pm.extractPath(pm.length - tail, pm.length), paint);
- });
- }
- }
|