88 lines
2.7 KiB
Dart
88 lines
2.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import '../../models/maps/japan_map_data.dart';
|
|
import '../../theme/app_theme.dart';
|
|
|
|
class PixelJapanMap extends StatelessWidget {
|
|
final Set<String> visitedPrefectures;
|
|
final Function(String prefecture)? onPrefectureTap;
|
|
|
|
const PixelJapanMap({
|
|
super.key,
|
|
required this.visitedPrefectures,
|
|
this.onPrefectureTap,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// Determine grid dimensions
|
|
final rows = JapanMapData.gridLayout.length;
|
|
final cols = JapanMapData.gridLayout[0].length;
|
|
|
|
// Fixed base cell size for drawing - FittedBox will scale it to screen
|
|
// Increased to 32.0 for better touch targets (Hit Box), visual size will be smaller
|
|
const double touchSize = 32.0;
|
|
const double visualSize = 22.0; // Slightly larger for visibility
|
|
const double gap = 0.0; // Gap is now handled by padding inside cell
|
|
|
|
final totalWidth = cols * (touchSize + gap);
|
|
final totalHeight = rows * (touchSize + gap);
|
|
|
|
return SizedBox(
|
|
width: totalWidth,
|
|
height: totalHeight,
|
|
child: Column(
|
|
children: JapanMapData.gridLayout.map((row) {
|
|
return Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: row.map((prefId) {
|
|
return _buildCell(context, prefId, touchSize, visualSize);
|
|
}).toList(),
|
|
);
|
|
}).toList(),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildCell(BuildContext context, int prefId, double touchSize, double visualSize) {
|
|
if (prefId == 0) {
|
|
return SizedBox(width: touchSize, height: touchSize);
|
|
}
|
|
|
|
final prefName = JapanMapData.prefectureNames[prefId] ?? '';
|
|
final isVisited = visitedPrefectures.any((p) => p.startsWith(prefName.replaceAll(RegExp(r'[都道府県]'), '')));
|
|
|
|
Color color;
|
|
if (isVisited) {
|
|
color = AppTheme.posimaiBlue;
|
|
} else {
|
|
final regionId = JapanMapData.getRegionId(prefId);
|
|
color = (regionId % 2 == 0) ? Colors.grey[200]! : Colors.grey[300]!;
|
|
}
|
|
|
|
return GestureDetector(
|
|
behavior: HitTestBehavior.opaque, // Ensure touches on transparent padding are caught
|
|
onTap: () {
|
|
if (prefName.isNotEmpty && onPrefectureTap != null) {
|
|
onPrefectureTap!(prefName);
|
|
}
|
|
},
|
|
child: Container(
|
|
width: touchSize,
|
|
height: touchSize,
|
|
alignment: Alignment.center,
|
|
child: Tooltip(
|
|
message: prefName,
|
|
child: Container(
|
|
width: visualSize,
|
|
height: visualSize,
|
|
decoration: BoxDecoration(
|
|
color: color,
|
|
borderRadius: BorderRadius.circular(visualSize * 0.15),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|