Files
impact/lib/features/crop/widgets/crop_overlay.dart
2026-01-18 16:31:45 +01:00

179 lines
4.4 KiB
Dart

/// 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);
}
}
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,
);
}
@override
bool shouldRepaint(covariant _CropOverlayPainter oldDelegate) {
return cropSize != oldDelegate.cropSize || showGrid != oldDelegate.showGrid;
}
}