需求
- 支持点击增加多边形点位(我的是最多八个,可自定义)
- 支持拖动点位进行移动成不规则多边形
- 支持检测当拖动的多边形存在边和边相交的情况则相交的边变成警告色


import 'dart:ui'
import 'package:camera/app_allocation/app_style.dart'
import 'package:camera/app_allocation/item_constants.dart'
import 'package:flutter/material.dart'
class CustomAreaUtils extends StatefulWidget {
const CustomAreaUtils({super.key})
@override
State<CustomAreaUtils> createState() => _CustomAreaUtilsState()
}
class _CustomAreaUtilsState extends State<CustomAreaUtils> {
List<Offset> points = []
int maxPoints = 8
@override
void initState() {
super.initState()
points = [const Offset(50.0, 50.0), const Offset(300.0, 50.0), const Offset(300.0, 150.0), const Offset(50.0, 150.0)]
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: ItemConstants.screenWidth,
height: ItemConstants.cameraViewHeight,
color: Colors.red,
child: GestureDetector(
onPanStart: (details) {
// 检查点击的位置是否在某个点上,如果是,则将其标记为选定的点,此时执行拖动代码
bool pointClicked = false;
for (int i = 0; i < points.length; i++) {
if ((points[i] - details.localPosition).distanceSquared < 100) {
pointClicked = true
break
}
}
// 如果未在点上点击,则添加新的点
if (!pointClicked && points.length < maxPoints) {
setState(() {
points = List.from(points)..add(details.localPosition)
})
}
},
onPanUpdate: (details) {
// 检查点击的位置是否在某个点上,如果是,则将其标记为选定的点,此时执行拖动代码
for (int i = 0
if ((points[i] - details.localPosition).distanceSquared < 100) {
setState(() {
points[i] = details.localPosition
})
break
}
}
},
child: CustomPaint(painter: CustomAreaPainter(points)),
),
),
],
),
),
)
}
}
class CustomAreaPainter extends CustomPainter {
final List<Offset> points
CustomAreaPainter(this.points)
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..color = AppStyle().getColor.mainColor
..strokeWidth = 3.0
..strokeCap = StrokeCap.round
if (points.length > 1 && points.length <= 8) {
canvas.drawPoints(PointMode.polygon, points, paint)
if (points.length > 2) {
canvas.drawLine(points.first, points.last, paint)
}
}
for (int i = 0
canvas.drawCircle(points[i], 6.0, paint)
TextSpan span = TextSpan(
text: '${i + 1}',
style: const TextStyle(color: Colors.white, fontSize: 12.0),
)
TextPainter tp = TextPainter(
text: span,
textAlign: TextAlign.center,
textDirection: TextDirection.ltr,
)
tp.layout()
tp.paint(canvas, Offset(points[i].dx - 4, points[i].dy - 8))
}
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true
}
}