Home telegram - deviceAngleSampler
Post
Cancel

telegram - deviceAngleSampler

class PGCameraDeviceAngleSampler

@property (nonatomic, copy) void(^deviceOrientationChanged)(UIDeviceOrientation orientation);

@property (nonatomic, readonly) UIDeviceOrientation deviceOrientation;
@property (nonatomic, readonly) bool isMeasuring;
@property (nonatomic, readonly) CGFloat currentDeviceAngle;

- (void)startMeasuring;
- (void)stopMeasuring;

// init
// 关注:CMMotionManager
- (instancetype)init
{
    self = [super init];
    if (self != nil)
    {
        _deviceOrientation = UIDeviceOrientationUnknown;
        
        _motionManager = [[CMMotionManager alloc] init];
        _motionManager.accelerometerUpdateInterval = 1.0f;
        _motionManager.deviceMotionUpdateInterval = 1.0f;
        _motionManager.gyroUpdateInterval = 1.0f;
        _motionManager.magnetometerUpdateInterval = 1.0f;
        _motionQueue = [[NSOperationQueue alloc] init];
    }
    return self;
}


- (void)dealloc
{
    [self stopMeasuring];
}

- (bool)isMeasuring
{
    return [_motionManager isDeviceMotionActive];
}

- (void)stopMeasuring
{
    [_motionManager stopDeviceMotionUpdates];
}

- (void)startMeasuring
{    
    if (![_motionManager isDeviceMotionAvailable])
        return;
    
    __weak PGCameraDeviceAngleSampler *weakSelf = self;
    [_motionManager startAccelerometerUpdatesToQueue:_motionQueue withHandler:^(CMAccelerometerData *accelerometerData, __unused NSError *error)
    {
        __strong PGCameraDeviceAngleSampler *strongSelf = weakSelf;
        if (strongSelf == nil || accelerometerData == nil || error != nil)
            return;
        
        CMAcceleration acceleration = accelerometerData.acceleration;
        CGFloat xx = -acceleration.x;
        CGFloat yy = acceleration.y;
        CGFloat z = acceleration.z;
        CGFloat angle = atan2(yy, xx);
        
        UIDeviceOrientation deviceOrientation = strongSelf.deviceOrientation;
        CGFloat absoluteZ = fabs(z);
        
        if (deviceOrientation == UIDeviceOrientationFaceUp || deviceOrientation == UIDeviceOrientationFaceDown)
        {
            if (absoluteZ < 0.845f)
            {
                if (angle < -2.6f)
                    deviceOrientation = UIDeviceOrientationLandscapeRight;
                else if (angle > -2.05f && angle < -1.1f)
                    deviceOrientation = UIDeviceOrientationPortrait;
                else if (angle > -0.48f && angle < 0.48f)
                    deviceOrientation = UIDeviceOrientationLandscapeLeft;
                else if (angle > 1.08f && angle < 2.08f)
                    deviceOrientation = UIDeviceOrientationPortraitUpsideDown;
            }
            else if (z < 0.f)
            {
                deviceOrientation = UIDeviceOrientationFaceUp;
            }
            else if (z > 0.f)
            {
                deviceOrientation = UIDeviceOrientationFaceDown;
            }
        }
        else
        {
            if (z > 0.875f)
            {
                deviceOrientation = UIDeviceOrientationFaceDown;
            }
            else if (z < -0.875f)
            {
                deviceOrientation = UIDeviceOrientationFaceUp;
            }
            else
            {
                switch (deviceOrientation)
                {
                    case UIDeviceOrientationLandscapeLeft:
                        if (angle < -1.07f) deviceOrientation = UIDeviceOrientationPortrait;
                        if (angle > 1.08f) deviceOrientation = UIDeviceOrientationPortraitUpsideDown;
                        break;
                        
                    case UIDeviceOrientationLandscapeRight:
                        if (angle < 0.f && angle > -2.05f) deviceOrientation = UIDeviceOrientationPortrait;
                        if (angle > 0.f && angle < 2.05f) deviceOrientation = UIDeviceOrientationPortraitUpsideDown;
                        break;
                        
                    case UIDeviceOrientationPortraitUpsideDown:
                        if (angle > 2.66f) deviceOrientation = UIDeviceOrientationLandscapeRight;
                        if (angle < 0.48f) deviceOrientation = UIDeviceOrientationLandscapeLeft;
                        break;
                        
                    case UIDeviceOrientationPortrait:
                    default:
                        if (angle > -0.47f) deviceOrientation = UIDeviceOrientationLandscapeLeft;
                        if (angle < -2.64f) deviceOrientation = UIDeviceOrientationLandscapeRight;
                        break;
                }
            }
        }
        
        if (deviceOrientation != strongSelf.deviceOrientation)
        {
            strongSelf->_deviceOrientation = deviceOrientation;
            
            TGDispatchOnMainThread(^
            {
                if (strongSelf.deviceOrientationChanged != nil)
                    strongSelf.deviceOrientationChanged(deviceOrientation);
            });
        }

    }];
    
    [_motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryZVertical toQueue:_motionQueue withHandler:^(CMDeviceMotion *motion, __unused NSError *error)
    {
        __strong PGCameraDeviceAngleSampler *strongSelf = weakSelf;
        if (strongSelf == nil)
            return;
        
        strongSelf->_currentDeviceAngle = TGRadiansToDegrees((CGFloat)(atan2(motion.gravity.x, motion.gravity.y) - M_PI)) * -1;
    }];
}
This post is licensed under CC BY 4.0 by the author.