refactor: ExposureSliderPainter を別ファイルに切り出し
camera_screen.dart の末尾にあった _ExposureSliderPainter (60行) を lib/screens/camera_exposure_painter.dart に分離。 動作変更なし。718行 → 659行。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b7f5edf9a9
commit
cc5175ebae
|
|
@ -0,0 +1,70 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// カメラ画面右端の露出スライダーを描画する CustomPainter。
|
||||||
|
///
|
||||||
|
/// - 縦トラック(白半透明)
|
||||||
|
/// - 中央基準線(0 EV を示すマーカー)
|
||||||
|
/// - 現在値を示すノブ(影付き白丸)
|
||||||
|
class ExposureSliderPainter extends CustomPainter {
|
||||||
|
final double currentValue;
|
||||||
|
final double minValue;
|
||||||
|
final double maxValue;
|
||||||
|
|
||||||
|
const ExposureSliderPainter({
|
||||||
|
required this.currentValue,
|
||||||
|
required this.minValue,
|
||||||
|
required this.maxValue,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
final trackPaint = Paint()
|
||||||
|
..color = Colors.white.withValues(alpha: 0.3)
|
||||||
|
..strokeWidth = 4
|
||||||
|
..strokeCap = StrokeCap.round;
|
||||||
|
|
||||||
|
final centerLinePaint = Paint()
|
||||||
|
..color = Colors.white54
|
||||||
|
..strokeWidth = 2;
|
||||||
|
|
||||||
|
final knobPaint = Paint()
|
||||||
|
..color = Colors.white
|
||||||
|
..style = PaintingStyle.fill;
|
||||||
|
|
||||||
|
final knobShadowPaint = Paint()
|
||||||
|
..color = Colors.black26
|
||||||
|
..maskFilter = const MaskFilter.blur(BlurStyle.normal, 4);
|
||||||
|
|
||||||
|
// 縦トラック(中央線)
|
||||||
|
final trackX = size.width / 2;
|
||||||
|
canvas.drawLine(
|
||||||
|
Offset(trackX, 10),
|
||||||
|
Offset(trackX, size.height - 10),
|
||||||
|
trackPaint,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 0 EV マーカー
|
||||||
|
canvas.drawLine(
|
||||||
|
Offset(trackX - 6, size.height / 2),
|
||||||
|
Offset(trackX + 6, size.height / 2),
|
||||||
|
centerLinePaint,
|
||||||
|
);
|
||||||
|
|
||||||
|
// ノブ位置を算出
|
||||||
|
final range = maxValue - minValue;
|
||||||
|
if (range > 0) {
|
||||||
|
// minValue(下端) → 0.0、maxValue(上端) → 1.0 に正規化してY座標に変換
|
||||||
|
final normalized = (currentValue - minValue) / range;
|
||||||
|
final knobY = (size.height - 20) * (1.0 - normalized) + 10;
|
||||||
|
canvas.drawCircle(Offset(trackX, knobY), 7, knobShadowPaint);
|
||||||
|
canvas.drawCircle(Offset(trackX, knobY), 6, knobPaint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(ExposureSliderPainter oldDelegate) {
|
||||||
|
return oldDelegate.currentValue != currentValue ||
|
||||||
|
oldDelegate.minValue != minValue ||
|
||||||
|
oldDelegate.maxValue != maxValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,6 +13,7 @@ import 'package:image_picker/image_picker.dart'; // Gallery & Camera
|
||||||
import '../services/image_compression_service.dart';
|
import '../services/image_compression_service.dart';
|
||||||
import '../theme/app_colors.dart';
|
import '../theme/app_colors.dart';
|
||||||
import 'camera_analysis_mixin.dart';
|
import 'camera_analysis_mixin.dart';
|
||||||
|
import 'camera_exposure_painter.dart';
|
||||||
|
|
||||||
|
|
||||||
enum CameraMode {
|
enum CameraMode {
|
||||||
|
|
@ -475,8 +476,8 @@ class _CameraScreenState extends ConsumerState<CameraScreen> with SingleTickerPr
|
||||||
height: 180,
|
height: 180,
|
||||||
width: 48, // Wider for easier tapping
|
width: 48, // Wider for easier tapping
|
||||||
child: CustomPaint(
|
child: CustomPaint(
|
||||||
key: ValueKey(_currentExposureOffset), // Force repaint on value change
|
key: ValueKey(_currentExposureOffset),
|
||||||
painter: _ExposureSliderPainter(
|
painter: ExposureSliderPainter(
|
||||||
currentValue: _currentExposureOffset,
|
currentValue: _currentExposureOffset,
|
||||||
minValue: _minExposure,
|
minValue: _minExposure,
|
||||||
maxValue: _maxExposure,
|
maxValue: _maxExposure,
|
||||||
|
|
@ -656,63 +657,3 @@ class _CameraScreenState extends ConsumerState<CameraScreen> with SingleTickerPr
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom Painter for Exposure Slider
|
|
||||||
class _ExposureSliderPainter extends CustomPainter {
|
|
||||||
final double currentValue;
|
|
||||||
final double minValue;
|
|
||||||
final double maxValue;
|
|
||||||
|
|
||||||
_ExposureSliderPainter({
|
|
||||||
required this.currentValue,
|
|
||||||
required this.minValue,
|
|
||||||
required this.maxValue,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
void paint(Canvas canvas, Size size) {
|
|
||||||
final trackPaint = Paint()
|
|
||||||
..color = Colors.white.withValues(alpha: 0.3)
|
|
||||||
..strokeWidth = 4
|
|
||||||
..strokeCap = StrokeCap.round;
|
|
||||||
|
|
||||||
final centerLinePaint = Paint()
|
|
||||||
..color = Colors.white54
|
|
||||||
..strokeWidth = 2;
|
|
||||||
|
|
||||||
final knobPaint = Paint()
|
|
||||||
..color = Colors.white
|
|
||||||
..style = PaintingStyle.fill; final knobShadowPaint = Paint()
|
|
||||||
..color = Colors.black26
|
|
||||||
..maskFilter = const MaskFilter.blur(BlurStyle.normal, 4); // Draw vertical track (centered)
|
|
||||||
final trackX = size.width / 2;
|
|
||||||
canvas.drawLine(
|
|
||||||
Offset(trackX, 10),
|
|
||||||
Offset(trackX, size.height - 10),
|
|
||||||
trackPaint,
|
|
||||||
); // Draw center marker
|
|
||||||
canvas.drawLine(
|
|
||||||
Offset(trackX - 6, size.height / 2),
|
|
||||||
Offset(trackX + 6, size.height / 2),
|
|
||||||
centerLinePaint,
|
|
||||||
); // Calculate knob position
|
|
||||||
final range = maxValue - minValue;
|
|
||||||
if (range > 0) {
|
|
||||||
// Normalize currentValue to 0.0-1.0 range
|
|
||||||
// minValue (e.g., -4.0) -> 0.0 (bottom)
|
|
||||||
// 0.0 (center) -> 0.5 (middle)
|
|
||||||
// maxValue (e.g., +4.0) -> 1.0 (top)
|
|
||||||
final normalized = (currentValue - minValue) / range;
|
|
||||||
// Map to Y coordinate: 0.0 (normalized) -> bottom, 1.0 (normalized) -> top
|
|
||||||
final knobY = (size.height - 20) * (1.0 - normalized) + 10;
|
|
||||||
// Draw knob shadow
|
|
||||||
canvas.drawCircle(Offset(trackX, knobY), 7, knobShadowPaint);
|
|
||||||
// Draw knob
|
|
||||||
canvas.drawCircle(Offset(trackX, knobY), 6, knobPaint);
|
|
||||||
}
|
|
||||||
} @override
|
|
||||||
bool shouldRepaint(_ExposureSliderPainter oldDelegate) {
|
|
||||||
return oldDelegate.currentValue != currentValue ||
|
|
||||||
oldDelegate.minValue != minValue ||
|
|
||||||
oldDelegate.maxValue != maxValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 1.0.41+48
|
version: 1.0.42+49
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.10.1
|
sdk: ^3.10.1
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue