flyToLocationWithBearing method
Flies to location with bearing calculated from movement direction in OTS view
Implementation
Future<void> flyToLocationWithBearing(RaliPosition position, {
double? bearing,
double zoom = 17.0,
double pitch = 70.0,
int duration = 100, // Very short duration for smoother navigation
double? speed,
}) async {
try {
// Throttle updates to prevent too many animations stacking
final now = DateTime.now();
if (now.difference(_lastCameraUpdate).inMilliseconds < 20) {
// Skip this update if too soon after the last one
return;
}
_lastCameraUpdate = now;
if (DebugSettings.showCameraLogs) {
print('[CAMERA] Updating camera: pos=${position.lat},${position.lng} bearing=${bearing ?? 0} animating=$_isCameraAnimating');
}
// Calculate dynamic puck position based on speed
// Position ranges from 10% from bottom at normal speeds to 30% at crawling speeds
final speedKmh = speed ?? 0.0;
double puckPositionPercentage = 0.1; // Default 10% from bottom
// At lower speeds, move puck position upward
if (speedKmh < 5.0) {
puckPositionPercentage = 0.3; // 30% from bottom at very low speeds
} else if (speedKmh < 15.0) {
// Linear interpolation between 30% and 10% based on speed
puckPositionPercentage = 0.3 - (speedKmh - 5.0) * (0.2 / 10.0);
}
// Get map size to calculate actual padding
final mapSize = await mapboxMap.getSize();
final screenHeight = mapSize != null && mapSize.height != null
? mapSize.height.toDouble()
: 500.0;
// Calculate bottom padding in pixels
final bottomPadding = screenHeight * puckPositionPercentage;
debugPrint("[DEBUG] Dynamic puck position: ${(puckPositionPercentage * 100).toStringAsFixed(1)}% from bottom (${bottomPadding.toStringAsFixed(1)}px) at speed ${speedKmh.toStringAsFixed(1)} km/h");
// Convert to Mapbox position
final mapboxPosition = mapbox.Position(position.lng, position.lat);
final point = mapbox.Point(coordinates: mapboxPosition);
// Create camera options with the calculated padding
final camera = mapbox.CameraOptions(
center: point,
zoom: zoom,
bearing: bearing ?? 0.0,
pitch: pitch,
padding: mapbox.MbxEdgeInsets(
top: 0,
left: 0,
right: 0,
bottom: bottomPadding, // Dynamic padding based on speed
),
);
// If we're already animating, use direct camera update to prevent animation queuing
if (_isCameraAnimating) {
await mapboxMap.setCamera(camera);
return;
}
// Mark animation starting
_isCameraAnimating = true;
// Use very short animation duration for smoother navigation
await mapboxMap.flyTo(
camera,
mapbox.MapAnimationOptions(
duration: duration,
)
);
// Mark animation complete
_isCameraAnimating = false;
} catch (e) {
print('Error moving camera with bearing: $e');
_isCameraAnimating = false; // Ensure flag is reset on error
// Attempt direct camera update as fallback
try {
await mapboxMap.setCamera(
mapbox.CameraOptions(
center: mapbox.Point(
coordinates: mapbox.Position(position.lng, position.lat)
),
zoom: zoom,
bearing: bearing ?? 0.0,
pitch: pitch
)
);
} catch (e2) {
print('Fallback direct camera update also failed: $e2');
}
}
}