map follow on drone focus. rubberband pointing to next waypoint. drone icon bigger 40px

This commit is contained in:
Constantin Leue
2026-08-03 22:07:11 +02:00
parent 7b198e1755
commit 2f4353f3fa
8 changed files with 152 additions and 36 deletions
+1 -1
View File
@@ -10,7 +10,7 @@ import 'package:flutter/material.dart';
/// dasselbe Muster). Zeigt unrotiert (Spitze nach oben) bei fehlendem
/// [headingDeg], sonst im Uhrzeigersinn um den Kurs ueber Grund gedreht.
class DroneMarkerIcon extends StatelessWidget {
const DroneMarkerIcon({super.key, this.size = 28, this.headingDeg});
const DroneMarkerIcon({super.key, this.size = 40, this.headingDeg});
final double size;
+24 -6
View File
@@ -3,26 +3,42 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:latlong2/latlong.dart';
import '../providers/current_mission_provider.dart';
import '../providers/follow_drone_provider.dart';
import '../providers/map_controller_provider.dart';
import '../providers/telemetry_provider.dart';
import 'nav_icon_button.dart';
/// Kartensteuerung im Fly-Modus (Doku 3.11): Ortssuche/Home entfallen hier
/// (keine Missionsbearbeitung), stattdessen zoomt der Drohnen-Button auf die
/// live Telemetrieposition - "Home" (erster Wegpunkt) ist waehrend des
/// Flugs kein sinnvoller Bezugspunkt mehr, der Fit-Button (gesamte Route)
/// bleibt dagegen unveraendert wie im Plan-Modus erhalten.
/// (keine Missionsbearbeitung), stattdessen schaltet der Drohnen-Button den
/// Kartenfolgemodus um (followDroneProvider) - "Home" (erster Wegpunkt) ist
/// waehrend des Flugs kein sinnvoller Bezugspunkt mehr, der Fit-Button
/// (gesamte Route) bleibt dagegen unveraendert wie im Plan-Modus erhalten.
class FlyMapControls extends ConsumerWidget {
const FlyMapControls({super.key});
/// Zielzoom beim Aktivieren des Folgemodus - naeher als der
/// Standard-Kartenzoom (siehe MissionMap._initialZoom), damit der Sprung
/// tatsaechlich als Zoom wahrgenommen wird und nicht nur als Verschieben.
static const _followZoom = 18.0;
/// Erster Tap zoomt auf die aktuelle Telemetrieposition und aktiviert den
/// Folgemodus (FlyScreen haengt sich darauf ein, zieht die Karte bei
/// jedem neuen Telemetrie-Frame nach und bricht bei manueller
/// Karteninteraktion selbststaendig wieder ab). Zweiter Tap beendet ihn
/// wieder, ohne die Kamera zu bewegen.
void _onDronePressed(BuildContext context, WidgetRef ref) {
if (ref.read(followDroneProvider)) {
ref.read(followDroneProvider.notifier).set(false);
return;
}
final frame = ref.read(telemetryProvider).value;
if (frame == null) {
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(content: Text('No telemetry yet')));
return;
}
ref.read(mapControllerProvider).move(LatLng(frame.lat, frame.lon), 16);
ref.read(mapControllerProvider).move(LatLng(frame.lat, frame.lon), _followZoom);
ref.read(followDroneProvider.notifier).set(true);
}
void _onFitPressed(BuildContext context, WidgetRef ref) {
@@ -37,11 +53,13 @@ class FlyMapControls extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final following = ref.watch(followDroneProvider);
return Row(
mainAxisSize: MainAxisSize.min,
children: [
NavIconButton(
icon: Icons.my_location,
icon: following ? Icons.gps_fixed : Icons.my_location,
active: following,
onTap: () => _onDronePressed(context, ref),
),
const SizedBox(width: 8),
+5 -2
View File
@@ -37,8 +37,11 @@ class MissionMap extends StatelessWidget {
/// markierte Segmente ueberschreiten Steig-/Sinkrate oder Kurvenradius.
final List<RouteSegment> routeSegments;
/// Gestrichelte Vorschaulinie vom letzten Wegpunkt zur aktuellen
/// Kartenmitte, waehrend noch kein neuer Punkt bestaetigt wurde.
/// Gestrichelte Verbindungslinie, Bedeutung je nach Modus: im Plan-Modus
/// vom letzten Wegpunkt zur aktuellen Kartenmitte, solange noch kein
/// neuer Punkt bestaetigt wurde (PlanScreen); im Fly-Modus von der
/// Drohne zum aktiven Wegpunkt (FlyScreen, TelemetryFrame.
/// activeWaypointIndex).
final List<LatLng>? rubberBandLine;
final VoidCallback? onMapReady;
+13 -1
View File
@@ -4,11 +4,20 @@ import 'package:flutter/material.dart';
/// Plan- (MapSearchControls: Home/Fit) und Fly-Modus-Kartensteuerungen
/// (FlyMapControls: Drohne/Fit).
class NavIconButton extends StatelessWidget {
const NavIconButton({super.key, required this.icon, required this.onTap});
const NavIconButton({
super.key,
required this.icon,
required this.onTap,
this.active = false,
});
final IconData icon;
final VoidCallback onTap;
/// Rosa Akzentrand (Doku 3.10: DroneMarkerIcon-Farbe) fuer Knoepfe mit
/// an/aus-Zustand, z.B. den Drohnen-Folgemodus (FlyMapControls).
final bool active;
@override
Widget build(BuildContext context) {
return GestureDetector(
@@ -19,6 +28,9 @@ class NavIconButton extends StatelessWidget {
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.black.withValues(alpha: 0.55),
border: active
? Border.all(color: const Color(0xFFFF2E93), width: 2)
: null,
),
child: Icon(icon, color: Colors.white, size: 16),
),