/// Overlay visuel pour le recadrage d'image. /// /// Affiche un masque semi-transparent avec une zone carrée transparente /// au centre pour indiquer la zone de recadrage. library; import 'package:flutter/material.dart'; class CropOverlay extends StatelessWidget { /// Taille du carré de recadrage (côté en pixels) final double cropSize; /// Afficher la grille des tiers final bool showGrid; const CropOverlay({super.key, required this.cropSize, this.showGrid = true}); @override Widget build(BuildContext context) { return CustomPaint( size: Size.infinite, painter: _CropOverlayPainter(cropSize: cropSize, showGrid: showGrid), ); } } class _CropOverlayPainter extends CustomPainter { final double cropSize; final bool showGrid; _CropOverlayPainter({required this.cropSize, required this.showGrid}); @override void paint(Canvas canvas, Size size) { // Calculer la position du carré centré final cropRect = Rect.fromCenter( center: Offset(size.width / 2, size.height / 2), width: cropSize, height: cropSize, ); // Dessiner le masque semi-transparent final maskPaint = Paint() ..color = Colors.black.withValues(alpha: 0.6) ..style = PaintingStyle.fill; // Créer un path pour le masque (tout sauf le carré central) final maskPath = Path() ..addRect(Rect.fromLTWH(0, 0, size.width, size.height)) ..addRect(cropRect) ..fillType = PathFillType.evenOdd; canvas.drawPath(maskPath, maskPaint); // Dessiner la bordure du carré de recadrage final borderPaint = Paint() ..color = Colors.white ..style = PaintingStyle.stroke ..strokeWidth = 2; canvas.drawRect(cropRect, borderPaint); // Dessiner les coins accentués _drawCorners(canvas, cropRect); // Dessiner la grille des tiers si activée if (showGrid) { _drawGrid(canvas, cropRect); } // Dessiner le point central (croix interne vert fluo) _drawCenterPoint(canvas, cropRect); } void _drawCorners(Canvas canvas, Rect rect) { final cornerPaint = Paint() ..color = Colors.white ..style = PaintingStyle.stroke ..strokeWidth = 4 ..strokeCap = StrokeCap.round; const cornerLength = 20.0; // Coin supérieur gauche canvas.drawLine( Offset(rect.left, rect.top + cornerLength), Offset(rect.left, rect.top), cornerPaint, ); canvas.drawLine( Offset(rect.left, rect.top), Offset(rect.left + cornerLength, rect.top), cornerPaint, ); // Coin supérieur droit canvas.drawLine( Offset(rect.right - cornerLength, rect.top), Offset(rect.right, rect.top), cornerPaint, ); canvas.drawLine( Offset(rect.right, rect.top), Offset(rect.right, rect.top + cornerLength), cornerPaint, ); // Coin inférieur gauche canvas.drawLine( Offset(rect.left, rect.bottom - cornerLength), Offset(rect.left, rect.bottom), cornerPaint, ); canvas.drawLine( Offset(rect.left, rect.bottom), Offset(rect.left + cornerLength, rect.bottom), cornerPaint, ); // Coin inférieur droit canvas.drawLine( Offset(rect.right - cornerLength, rect.bottom), Offset(rect.right, rect.bottom), cornerPaint, ); canvas.drawLine( Offset(rect.right, rect.bottom), Offset(rect.right, rect.bottom - cornerLength), cornerPaint, ); } void _drawGrid(Canvas canvas, Rect rect) { final gridPaint = Paint() ..color = Colors.white.withValues(alpha: 0.4) ..style = PaintingStyle.stroke ..strokeWidth = 1; final thirdWidth = rect.width / 3; final thirdHeight = rect.height / 3; // Lignes verticales canvas.drawLine( Offset(rect.left + thirdWidth, rect.top), Offset(rect.left + thirdWidth, rect.bottom), gridPaint, ); canvas.drawLine( Offset(rect.left + thirdWidth * 2, rect.top), Offset(rect.left + thirdWidth * 2, rect.bottom), gridPaint, ); // Lignes horizontales canvas.drawLine( Offset(rect.left, rect.top + thirdHeight), Offset(rect.right, rect.top + thirdHeight), gridPaint, ); canvas.drawLine( Offset(rect.left, rect.top + thirdHeight * 2), Offset(rect.right, rect.top + thirdHeight * 2), gridPaint, ); } void _drawCenterPoint(Canvas canvas, Rect rect) { // Peinture de la croix interne (Vert Fluo) final centerPaint = Paint() ..color = const Color(0xFF00FF00) ..style = PaintingStyle.stroke ..strokeWidth = 2.0; // Cercle extérieur (Vert Fluo fin) final circlePaint = Paint() ..color = const Color(0xFF00FF00).withValues(alpha: 0.9) ..style = PaintingStyle.stroke ..strokeWidth = 1.2; const circleRadius = 10.0; // Augmenté légèrement à 10 pour que la croix respire final centerX = rect.center.dx; final centerY = rect.center.dy; // 1. Dessiner le cercle de contour canvas.drawCircle(rect.center, circleRadius, circlePaint); // 2. Dessiner la croix UNIQUEMENT à l'intérieur du cercle // Ligne horizontale (de gauche à droite, reste à l'intérieur) canvas.drawLine( Offset(centerX - circleRadius, centerY), Offset(centerX + circleRadius, centerY), centerPaint, ); // Ligne verticale (de haut en bas, reste à l'intérieur) canvas.drawLine( Offset(centerX, centerY - circleRadius), Offset(centerX, centerY + circleRadius), centerPaint, ); } @override bool shouldRepaint(covariant _CropOverlayPainter oldDelegate) { return cropSize != oldDelegate.cropSize || showGrid != oldDelegate.showGrid; } }