So i have a custom map 4x3 And this is what I want to do: when I tap on two different squares, it shows a line (like a polyline) from square 1 to square 2.
I haven't found a solution to achieve this yet
Please help me. Do you have any suggestions on how to achieve this? Are there any recommended libraries for accomplishing this task?
Here is the code i handmade custom using custompaint:
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Center(
child: Image.asset(
'assets/Sơ đồ mô phỏng.png',
height: 300,
),
),
CustomPaint(
painter: MyPainter(),
),
Positioned(
top: 50,
left: 10,
child: IconButton(
onPressed: () {},
icon: const Icon(
Icons.map,
size: 35,
),
),
),
Positioned(
top: 100,
left: 10,
child: IconButton(
onPressed: () {},
icon: const Icon(
Icons.pattern_sharp,
size: 35,
),
),
),
Positioned(
top: 150,
left: 10,
child: IconButton(
onPressed: () {},
icon: const Icon(
Icons.location_on,
size: 35,
),
),
)
],
),
);
}
}
class MyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
const p1 = Offset(165, 100);
const p2 = Offset(165, 135);
final paint1 = Paint()
..color = Colors.black
..strokeJoin
..strokeWidth = 3;
const p3 = Offset(165, 135);
const p4 = Offset(490, 135);
final paint2 = Paint()
..color = Colors.black
..strokeWidth = 3;
const p5 = Offset(490, 100);
const p6 = Offset(490, 135);
final paint3 = Paint()
..color = Colors.black
..strokeWidth = 3;
canvas.drawLine(p1, p2, paint1);
canvas.drawLine(p3, p4, paint2);
canvas.drawLine(p5, p6, paint3);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
i solve it here is the solution
class TestDraw2Point extends StatefulWidget {
@override
_TestDraw2PointState createState() => _TestDraw2PointState();
}
class _TestDraw2PointState extends State<TestDraw2Point> {
List<Offset> _points = [];
void _addPoint(Offset point) {
setState(() {
_points.add(point);
if (_points.length == 2) {
_points = List.from(_points);
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Draw Line Example'),
),
body: GestureDetector(
onTapDown: (TapDownDetails details) {
_addPoint(details.localPosition);
},
child: CustomPaint(
painter: LinePainter(points: _points),
child: Container(),
),
),
);
}
}
class LinePainter extends CustomPainter {
List<Offset> points;
LinePainter({required this.points});
@override
void paint(Canvas canvas, Size size) {
if (points.length == 2) {
final paint = Paint()
..color = Colors.black
..strokeWidth = 3.0;
canvas.drawLine(points[0], points[1], paint);
}
}
@override
bool shouldRepaint(LinePainter oldDelegate) => true;
}
Here this another version to draw multiline
class DrawLineScreen extends StatefulWidget {
const DrawLineScreen({super.key});
@override
_DrawLineScreenState createState() => _DrawLineScreenState();
}
class _DrawLineScreenState extends State<DrawLineScreen> {
final List<Offset> _points = [];
final List<List<Offset>> _lines = [];
void _addPoint(Offset point) {
setState(() {
_points.add(point);
if (_points.length == 2) {
_lines.add(List.from(_points));
_points.clear();
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Draw Line Example'),
),
body: GestureDetector(
onTapDown: (TapDownDetails details) {
_addPoint(details.localPosition);
},
child: CustomPaint(
painter: LinePainter(lines: _lines, currentPoints: _points),
child: Container(),
),
),
);
}
}
class LinePainter extends CustomPainter {
List<List<Offset>> lines;
List<Offset> currentPoints;
LinePainter({required this.lines, required this.currentPoints});
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.black
..strokeWidth = 3.0;
for (final line in lines) {
canvas.drawLine(line[0], line[1], paint);
}
if (currentPoints.length == 2) {
canvas.drawLine(currentPoints[0], currentPoints[1], paint);
}
}
@override
bool shouldRepaint(LinePainter oldDelegate) => true;
}