feat: boutons de rotation fine sur l'ecran de centrage + consigne de cadrage
This commit is contained in:
@@ -27,6 +27,11 @@ class CropScreen extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _CropScreenState extends State<CropScreen> {
|
class _CropScreenState extends State<CropScreen> {
|
||||||
|
// Bornes et pas de la rotation, partagés par la jauge et les boutons − / +.
|
||||||
|
static const double _minRotation = -15.0;
|
||||||
|
static const double _maxRotation = 15.0;
|
||||||
|
static const double _rotationStep = 0.1;
|
||||||
|
|
||||||
final ImageCropService _cropService = ImageCropService();
|
final ImageCropService _cropService = ImageCropService();
|
||||||
|
|
||||||
// États de transformation
|
// États de transformation
|
||||||
@@ -113,7 +118,7 @@ class _CropScreenState extends State<CropScreen> {
|
|||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Flexible(
|
Flexible(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Alignez et pivotez la cible sur la croix',
|
'Zoomer au maximum puis aligner votre cible',
|
||||||
style: TextStyle(color: Colors.white.withValues(alpha: 0.8), fontSize: 14, fontWeight: FontWeight.w500),
|
style: TextStyle(color: Colors.white.withValues(alpha: 0.8), fontSize: 14, fontWeight: FontWeight.w500),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -155,7 +160,8 @@ class _CropScreenState extends State<CropScreen> {
|
|||||||
|
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
|
|
||||||
// CROIX DIRECTIONNELLE — déplace la photo pixel par pixel.
|
// CROIX DIRECTIONNELLE — déplace la photo pixel par pixel,
|
||||||
|
// encadrée par les deux boutons de rotation fine.
|
||||||
_buildDirectionalPad(),
|
_buildDirectionalPad(),
|
||||||
|
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
@@ -180,12 +186,13 @@ class _CropScreenState extends State<CropScreen> {
|
|||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.rotate_left, color: Colors.white38, size: 20),
|
// Les icônes de sens de rotation ont rejoint les boutons − / +
|
||||||
|
// de la croix directionnelle.
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Slider(
|
child: Slider(
|
||||||
value: _rotation,
|
value: _rotation,
|
||||||
min: -15.0,
|
min: _minRotation,
|
||||||
max: 15.0,
|
max: _maxRotation,
|
||||||
divisions: 300,
|
divisions: 300,
|
||||||
label: '${_rotation.toStringAsFixed(1)}°',
|
label: '${_rotation.toStringAsFixed(1)}°',
|
||||||
activeColor: const Color(0xFF1A73E8),
|
activeColor: const Color(0xFF1A73E8),
|
||||||
@@ -197,7 +204,6 @@ class _CropScreenState extends State<CropScreen> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Icon(Icons.rotate_right, color: Colors.white38, size: 20),
|
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.restart_alt, color: Colors.white54, size: 20),
|
icon: const Icon(Icons.restart_alt, color: Colors.white54, size: 20),
|
||||||
@@ -363,12 +369,18 @@ class _CropScreenState extends State<CropScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Croix directionnelle compacte pour déplacer la photo pixel par pixel.
|
// Croix directionnelle compacte pour déplacer la photo pixel par pixel.
|
||||||
// Les symboles « − » et « + » de part et d'autre sont purement décoratifs.
|
// Les boutons « − » et « + » de part et d'autre pivotent l'image de 0,1°.
|
||||||
Widget _buildDirectionalPad() {
|
Widget _buildDirectionalPad() {
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
_buildCropSignLabel('−'),
|
_buildRotationButton(
|
||||||
|
icon: Icons.rotate_left,
|
||||||
|
sign: '−',
|
||||||
|
iconFirst: true,
|
||||||
|
tooltip: 'Pivoter vers la gauche',
|
||||||
|
onPressed: () => _rotateBy(-_rotationStep),
|
||||||
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Column(
|
Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -386,7 +398,13 @@ class _CropScreenState extends State<CropScreen> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
_buildCropSignLabel('+'),
|
_buildRotationButton(
|
||||||
|
icon: Icons.rotate_right,
|
||||||
|
sign: '+',
|
||||||
|
iconFirst: false,
|
||||||
|
tooltip: 'Pivoter vers la droite',
|
||||||
|
onPressed: () => _rotateBy(_rotationStep),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -404,10 +422,40 @@ class _CropScreenState extends State<CropScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildCropSignLabel(String text) {
|
// Bouton de rotation : l'icône de sens est accolée au signe − / +.
|
||||||
return Text(
|
Widget _buildRotationButton({
|
||||||
text,
|
required IconData icon,
|
||||||
style: const TextStyle(color: Colors.white54, fontSize: 24, fontWeight: FontWeight.bold),
|
required String sign,
|
||||||
|
required bool iconFirst,
|
||||||
|
required String tooltip,
|
||||||
|
required VoidCallback onPressed,
|
||||||
|
}) {
|
||||||
|
final content = [
|
||||||
|
Icon(icon, color: Colors.white70, size: 20),
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
Text(
|
||||||
|
sign,
|
||||||
|
style: const TextStyle(color: Colors.white, fontSize: 22, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
return Tooltip(
|
||||||
|
message: tooltip,
|
||||||
|
child: Material(
|
||||||
|
color: Colors.black54,
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: onPressed,
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: iconFirst ? content : content.reversed.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,6 +465,17 @@ class _CropScreenState extends State<CropScreen> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pivote l'image de [delta] degrés, dans les mêmes bornes que la jauge.
|
||||||
|
///
|
||||||
|
/// La valeur est arrondie au dixième pour rester calée sur les crans de la
|
||||||
|
/// jauge (300 divisions sur 30°) et sur l'affichage.
|
||||||
|
void _rotateBy(double delta) {
|
||||||
|
setState(() {
|
||||||
|
final value = (_rotation + delta).clamp(_minRotation, _maxRotation);
|
||||||
|
_rotation = (value * 10).roundToDouble() / 10;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void _onScaleStart(ScaleStartDetails details) {
|
void _onScaleStart(ScaleStartDetails details) {
|
||||||
_baseScale = _scale;
|
_baseScale = _scale;
|
||||||
_startFocalPoint = details.focalPoint;
|
_startFocalPoint = details.focalPoint;
|
||||||
|
|||||||
Reference in New Issue
Block a user