123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- 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, {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, this.titlesList, this.minRadius, 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,
- 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);
- });
- }
- }
|