import 'dart:math'; import 'dart:ui'; import 'package:flutter/material.dart'; import 'dart:ui' as ui; import '../components/coordinate_pro.dart'; import 'touch_info.dart'; /// create by 张风捷特烈 on 2020/5/1 /// contact me by email 1981462002@qq.com /// 说明: class Paper extends StatefulWidget { const Paper({super.key}); @override _PaperState createState() => _PaperState(); } class _PaperState extends State { final TouchInfo touchInfo = TouchInfo(); //单位圆(即半径为1)控制线长 final rate = 0.551915024494; double _radius = 150; @override void initState() { super.initState(); touchInfo.setPoints(_initPoints()); } @override void dispose() { touchInfo.dispose(); super.dispose(); } List _initPoints() { final List pos = []; //第一段线 pos.add(Offset(0, rate) * _radius); pos.add(Offset(1 - rate, 1) * _radius); pos.add(Offset(1, 1) * _radius); //第二段线 pos.add(Offset(1 + rate, 1) * _radius); pos.add(Offset(2, rate) * _radius); pos.add(Offset(2, 0) * _radius); //第三段线 pos.add(Offset(2, -rate) * _radius); pos.add(Offset(1 + rate, -1) * _radius); pos.add(Offset(1, -1) * _radius); //第四段线 pos.add(Offset(1 - rate, -1) * _radius); pos.add(Offset(0, -rate) * _radius); pos.add(Offset(0, 0)); return pos; } @override Widget build(BuildContext context) { return LayoutBuilder( builder:(_,cts)=> GestureDetector( onPanDown: (details)=>_onPanDown(details,cts.biggest), onPanUpdate: (details)=>_onPanUpdate(details,cts.biggest), child: Container( color: Colors.white, child: CustomPaint( painter: PaperPainter(repaint: touchInfo), ), ), ), ); } void _onPanDown(DragDownDetails details,Size size) { print("=====${details}===========${touchInfo.points.length}}"); if (touchInfo.points.length < 4) { touchInfo.addPoint(details.localPosition); } else { judgeZone(details.localPosition,size); } } void _onPanUpdate(DragUpdateDetails details,Size size) { judgeZone(details.localPosition,size, update: true); } ///判断出是否在某点的半径为r圆范围内 bool judgeCircleArea(Offset src, Offset dst, double r) => (src - dst).distance <= r; //判断哪个点被选中 void judgeZone(Offset src, Size size,{bool update = false}) { src= src.translate(-size.width/2, -size.height/2); for (int i = 0; i < touchInfo.points.length; i++) { if (judgeCircleArea(src, touchInfo.points[i], 15)) { touchInfo.selectIndex = i; if (update) { touchInfo.updatePoint(i, src); } } } } } class PaperPainter extends CustomPainter { final Coordinate coordinate = Coordinate(); Paint _helpPaint = Paint() ..color = Colors.purple ..style = PaintingStyle.stroke ..strokeCap = StrokeCap.round; final TouchInfo repaint; PaperPainter({required this.repaint}) : super(repaint: repaint); List pos = []; @override void paint(Canvas canvas, Size size) { coordinate.paint(canvas, size); canvas.translate(size.width / 2, size.height / 2); pos = repaint.points; Path path = Path(); Paint paint = Paint() ..color = Colors.orange ..style = PaintingStyle.stroke ..strokeWidth = 2; path.moveTo(0, 0); for (int i = 0; i < pos.length / 3; i++) { path.cubicTo(pos[3 * i + 0].dx, pos[3 * i + 0].dy, pos[3 * i + 1].dx, pos[3 * i + 1].dy, pos[3 * i + 2].dx, pos[3 * i + 2].dy); } canvas.drawPath(path, paint); _drawHelp(canvas); _drawSelectPos(canvas, size); } void _drawHelp(Canvas canvas) { _helpPaint..strokeWidth = 1..color=Colors.purple; canvas.drawLine(pos[0], pos[11], _helpPaint); canvas.drawLine(pos[1], pos[2], _helpPaint); canvas.drawLine(pos[2], pos[3], _helpPaint); canvas.drawLine(pos[4], pos[5], _helpPaint); canvas.drawLine(pos[5], pos[6], _helpPaint); canvas.drawLine(pos[7], pos[8], _helpPaint); canvas.drawLine(pos[8], pos[9], _helpPaint); canvas.drawLine(pos[10], pos[11], _helpPaint); canvas.drawLine(pos[11], pos[0], _helpPaint); canvas.drawPoints(PointMode.points, pos, _helpPaint..strokeWidth = 8); } void _drawSelectPos(Canvas canvas, Size size) { Offset? selectPos = repaint.selectPoint; if (selectPos == null) return; canvas.drawCircle(selectPos, 10, _helpPaint..color = Colors.green..strokeWidth = 2); } @override bool shouldRepaint(PaperPainter oldDelegate) => oldDelegate.repaint != repaint; }