fix(location): single-color route, contrasting arrows, time labels on endpoints

This commit is contained in:
2026-04-16 14:52:07 +02:00
parent bc46f31434
commit 1230a27d94
2 changed files with 60 additions and 41 deletions

View File

@@ -3,17 +3,18 @@ import 'dart:math' as math;
import 'package:control_panel/control_panel.dart';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:intl/intl.dart';
import 'package:latlong2/latlong.dart';
const _clusterBaseDegrees = 0.5;
const _clusterBaseZoom = 8;
const routeColor = Color(0xFF329E95);
const routeArrowColor = Color(0xFFFF6D00);
const routeStartColor = Color(0xFF4CAF50);
bool _hasValidCoords(PositionEntity p) => p.latitude != 0 || p.longitude != 0;
const routeEndColor = Color(0xFFF44336);
Color routeGradient(double t) => Color.lerp(routeStartColor, routeEndColor, t)!;
bool _hasValidCoords(PositionEntity p) => p.latitude != 0 || p.longitude != 0;
class RouteHistoryLayer extends StatelessWidget {
final List<PositionEntity> positionHistory;
@@ -39,24 +40,16 @@ class RouteHistoryLayer extends StatelessWidget {
List<Polyline> buildRouteSegments() {
if (positionHistory.length < 2) return [];
final segments = <Polyline>[];
for (int i = 0; i < positionHistory.length - 1; i++) {
final t = i / (positionHistory.length - 1);
segments.add(
Polyline(
points: [
LatLng(positionHistory[i].latitude, positionHistory[i].longitude),
LatLng(
positionHistory[i + 1].latitude,
positionHistory[i + 1].longitude,
),
],
color: routeGradient(t),
strokeWidth: 4.0,
),
);
}
return segments;
final points = positionHistory
.where(_hasValidCoords)
.map((p) => LatLng(p.latitude, p.longitude))
.toList();
if (points.length < 2) return [];
return [
Polyline(points: points, color: routeColor, strokeWidth: 4.0),
];
}
List<Marker> _buildDirectionArrows() {
@@ -66,26 +59,27 @@ class RouteHistoryLayer extends StatelessWidget {
for (int i = 0; i < positionHistory.length - 1; i++) {
final from = positionHistory[i];
final to = positionHistory[i + 1];
if (!_hasValidCoords(from)) continue;
if (!_hasValidCoords(to)) continue;
if (!_hasValidCoords(from) || !_hasValidCoords(to)) continue;
final midLat = (from.latitude + to.latitude) / 2;
final midLng = (from.longitude + to.longitude) / 2;
final angle = math.atan2(
final bearing = math.atan2(
to.longitude - from.longitude,
to.latitude - from.latitude,
);
final t = i / (positionHistory.length - 1);
arrows.add(
Marker(
point: LatLng(midLat, midLng),
width: 16,
height: 16,
width: 18,
height: 18,
child: Transform.rotate(
angle: -angle,
child: Icon(Icons.navigation, color: routeGradient(t), size: 16),
angle: bearing,
child: const Icon(
Icons.navigation,
color: routeArrowColor,
size: 18,
),
),
rotate: false,
),
@@ -149,18 +143,17 @@ class RouteHistoryLayer extends StatelessWidget {
for (final cluster in clustered) {
final firstIdx = cluster.first;
final position = intermediates[firstIdx];
final originalIdx = firstIdx + 1;
final t = originalIdx / (positionHistory.length - 1);
final color = routeGradient(t);
if (cluster.length == 1) {
markers.add(_buildIntermediateMarker(position: position, color: color));
markers.add(
_buildIntermediateMarker(position: position, color: routeColor),
);
} else {
markers.add(
_buildClusterMarker(
position: position,
count: cluster.length,
color: color,
color: routeColor,
),
);
}
@@ -174,16 +167,41 @@ class RouteHistoryLayer extends StatelessWidget {
required Color color,
required IconData icon,
}) {
final time = DateFormat.Hm().format(
DateTime.fromMillisecondsSinceEpoch(position.createdAt),
);
return Marker(
point: LatLng(position.latitude, position.longitude),
width: 32,
height: 32,
width: 64,
height: 52,
child: GestureDetector(
onTap: () => onPositionTap(position),
child: _CircleMarkerIcon(
color: color,
size: 32,
child: Icon(icon, color: Colors.white, size: 18),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_CircleMarkerIcon(
color: color,
size: 32,
child: Icon(icon, color: Colors.white, size: 18),
),
const SizedBox(height: 2),
Container(
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1),
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(4),
),
child: Text(
time,
style: const TextStyle(
color: Colors.white,
fontSize: 9,
fontWeight: FontWeight.w700,
),
),
),
],
),
),
rotate: true,

View File

@@ -38,6 +38,7 @@ dependencies:
flutter_svg: ^2.2.2
uuid: ^4.5.3
share_plus: ^10.1.4
intl: ^0.20.2
dev_dependencies:
flutter_test: