iOS 【陀螺儀 自身旋轉角&水平面夾角 問題】
阿新 • • 發佈:2019-02-13
在開發過程中,我們通常會遇到 獲取 iPhone 繞自身的旋轉角度 以及 獲取 iPhone 與水平面的夾角 這類需求。打個比方,在專案中,我們需要整合一個相機拍攝照片的功能。前提條件是讓只允許相機在橫屏狀態下進行拍攝,而豎屏狀態下禁止拍攝。如果要實現這個需求,那麼僅僅靠系統內建的相機 API 是無法實現的,那麼我們就需要自定義相機。而本文就是解決在自定義相機時如何顯示手機自身的狀態,並拿到這個狀態進而決定是否允許拍攝。
如下圖,分別是在我自定義相機拍攝時橫豎屏的一個介面展示狀態,正好描述了上文描述的一個情景:
可以發現,在豎屏狀態下時,會有一層灰黑色的蒙版,上面有提醒橫屏拍攝的標識語,按鈕也是禁用狀態,只有退出按鈕可用。而在橫屏狀態下時,拍照按鈕可用,提示標語和蒙版均消失。那麼,究竟怎麼才能實現橫豎屏的判定呢?
程式碼:
// // PushViewController.m // 陀螺儀 // // Created by CoderZYWang on 2016/12/26. // Copyright © 2016年 CoderZYWang. All rights reserved. // #import "PushViewController.h" #import <CoreMotion/CoreMotion.h> @interface PushViewController () @property (nonatomic, strong) CMMotionManager *motionManager; @end @implementation PushViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // 當前的view必須設定背景色,不然根本沒法觸發螢幕的點選事件 self.view.backgroundColor = [UIColor whiteColor]; } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self useGyroPush]; // 介面點選時就會呼叫陀螺儀 } - (void)viewDidDisappear:(BOOL)animated { // 該介面消失時一定要停止,不然會一直呼叫消耗記憶體 [self.motionManager stopDeviceMotionUpdates]; // 停止所有的裝置 // [self.motionManager stopAccelerometerUpdates]; // 加速度計 // [self.motionManager stopMagnetometerUpdates]; // 磁力計 // [self.motionManager stopGyroUpdates]; // 陀螺 } - (void)useGyroPush{ //初始化全域性管理物件 CMMotionManager *manager = [[CMMotionManager alloc] init]; self.motionManager = manager; if ([self.motionManager isDeviceMotionAvailable]) { manager.deviceMotionUpdateInterval = 1; [self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion * _Nullable motion, NSError * _Nullable error) { // Gravity 獲取手機的重力值在各個方向上的分量,根據這個就可以獲得手機的空間位置,傾斜角度等 double gravityX = motion.gravity.x; double gravityY = motion.gravity.y; double gravityZ = motion.gravity.z; // 獲取手機的傾斜角度(zTheta是手機與水平面的夾角, xyTheta是手機繞自身旋轉的角度): double zTheta = atan2(gravityZ,sqrtf(gravityX * gravityX + gravityY * gravityY)) / M_PI * 180.0; double xyTheta = atan2(gravityX, gravityY) / M_PI * 180.0; NSLog(@"手機與水平面的夾角 --- %.4f, 手機繞自身旋轉的角度為 --- %.4f", zTheta, xyTheta); }]; } } @end
通過我們上面 block 回撥的結果,我們可以精確的定位 iPhone 與水平面的夾角 以及 iPhone 繞自身旋轉的角度。這樣無論你的手機如何傾斜翻轉,我們都能拿到它當前的一個狀態。多次測試之後,就能獲取到你想要設定的一個狀態區間了。