| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- import 'dart:async';
- import 'dart:math' as math;
- import 'package:sensors_plus/sensors_plus.dart';
- class TiltDetector {
- static final TiltDetector _instance = TiltDetector._internal();
- factory TiltDetector() => _instance;
- TiltDetector._internal();
- StreamSubscription<AccelerometerEvent>? _accelerometerSubscription;
- Function(double)? onTiltChanged;
-
- bool _isListening = false;
- double _currentTilt = 0.0;
-
- // Filtering parameters to smooth out noise
- static const double _alpha = 0.8; // Low-pass filter constant
- double _filteredX = 0.0;
-
- bool get isListening => _isListening;
- double get currentTilt => _currentTilt;
- /// Start listening to accelerometer data
- /// [onTiltChanged] callback receives tilt angle in degrees
- /// Positive values = device tilted right, negative = tilted left
- void startListening({Function(double)? onTiltChanged}) {
- if (_isListening) return;
-
- this.onTiltChanged = onTiltChanged;
- _isListening = true;
-
- _accelerometerSubscription = accelerometerEventStream(
- samplingPeriod: const Duration(milliseconds: 100), // 10 Hz sampling rate
- ).listen(_onAccelerometerEvent);
- }
-
- /// Stop listening to accelerometer data
- void stopListening() {
- if (!_isListening) return;
-
- _accelerometerSubscription?.cancel();
- _accelerometerSubscription = null;
- _isListening = false;
- onTiltChanged = null;
- _currentTilt = 0.0;
- _filteredX = 0.0;
- }
-
- void _onAccelerometerEvent(AccelerometerEvent event) {
- // Apply low-pass filter to smooth out noise
- _filteredX = _alpha * _filteredX + (1 - _alpha) * event.x;
-
- // Calculate tilt angle in degrees
- // The accelerometer X axis represents left-right tilt
- // Clamp to reasonable tilt range (-45 to +45 degrees)
- final tiltRadians = math.atan2(_filteredX, 9.8);
- _currentTilt = (tiltRadians * 180 / math.pi).clamp(-45.0, 45.0);
-
- // Only trigger callback if tilt is significant (> 5 degrees)
- if (_currentTilt.abs() > 5.0) {
- onTiltChanged?.call(_currentTilt);
- }
- }
-
- /// Get normalized tilt strength from -1.0 to 1.0
- /// -1.0 = maximum left tilt, +1.0 = maximum right tilt
- double get normalizedTilt {
- return (_currentTilt / 45.0).clamp(-1.0, 1.0);
- }
-
- /// Check if device is significantly tilted
- bool get isTilted => _currentTilt.abs() > 5.0;
-
- /// Check if device is tilted left
- bool get isTiltedLeft => _currentTilt < -5.0;
-
- /// Check if device is tilted right
- bool get isTiltedRight => _currentTilt > 5.0;
- }
|