在寫上一個動畫系列的時候學到了非常多的知識,也認識了很多人。例如受邀進入了某個神祕的動效組織,全是一線的大神啊。有UI的大牛、UED的大神、iOS的大神。加入組織可以閱讀這裡:加入CRAnimation組織 。
真的是發現堅持寫作,其實也是逼迫自己堅持不斷學習的過程。那麼,來來來,星辰大海我們又開始啟程了。這次這個系列吶,我管它叫《iOS感測器小兄弟們》。先暫時這麼叫著,等想到什麼好聽的名字再改。
咳咳,下面這個計劃就真的只是計劃,反正現在先這麼計劃著。實在不行就改需求,需求就是用來改的......-_-+++。所以,以下目錄第一篇:加速感測器
第二篇:陀螺儀
第三篇:磁力計
第四篇:距離感測器
第五篇:指紋識別感測器
第六篇:藍芽之MultipeerConnectivity
第七篇:藍芽之Core Bluetooth
第八篇:想個好玩的例子,把前面的都綜合一下。
這個系列的內容模擬器基本上都不支援,需要真機測試才可以。所以掏出手機,我們們一起來搞事情吧。為了能夠錄到手機效果,也是小費了一番周折。
我們們通過實現一個隨螢幕旋轉的圖片來看看加速計怎麼玩。下面是完成後的效果視訊截圖,GIF圖片的壓縮效果也是剛剛的。請無視我的小背心:
有一些APP除了絢麗的介面之外,還會有一些特殊的功能。例如微信的搖一搖,各種健康軟體的計步器,指南針等等。這些APP其實都用到了iOS當中一個核心運動框架,叫做CoreMotion
。
CoreMotion可以從內建的感測器中獲取資料,這些感測器包括陀螺儀、加速器和磁力計。更值得嘚瑟的是,蘋果整合了很多演算法,可以直接輸出剝離重力加速因素的加速度資訊。好流弊的樣紙。
1. 加速計介紹
iPhone、iPad、iWatch都可以測量x,y,x三個軸上的加速力。加速力就是當物體在加速過程中作用在物體上的力。用一張圖說明一下下:
2. 加速計的使用
既然說了加速計是通過CoreMotion
這個框架來管理的,而且蘋果繼承了辣麼多演算法,所以CoreMotion一定還有一個Manager。官方是這麼介紹CMMotionManager:
A CMMotionManager object is the gateway to the motion services provided by iOS. These services provide an app with accelerometer data, rotation-rate data, magnetometer data, and other device-motion data such as attitude. These types of data originate with a device’s accelerometers and (on some models) its magnetometer and gyroscope.
所以只要使用Motion的服務,我們們一定需要使用CMMotionManager。 使用步驟如下:
- 初始化CMMotionManager管理物件;
- 呼叫管理物件的物件方法獲取資料;
- 處理資料;
- 當不需要使用的時候,停止獲取資料。
//初始化全域性管理物件
- (CMMotionManager *)manager{
if (!_manager) {
_manager = [[CMMotionManager alloc] init];
}
return _manager;
}
複製程式碼
//停止獲取加速計資料。在停止之前判斷一下是否還處在活動
if ( self.manager.accelerometerActive) {
[self.manager stopAccelerometerUpdates];
NSLog(@"關閉啦");
}
複製程式碼
3. 獲取加速計資料的兩種方式
CoreMotion中有2種獲取資料方式,一種叫做PUSH的方式,一種叫做PULL的方式。 顧名思義,PUSH就是被動的獲取。設定完了之後,執行緒定時把獲取到的資料推送回來。可想而知,對於資源的消耗是會稍微大一點的。
PULL,就是要去索取。拉一下才會獲取到資料。不要不給。
3.1 PULL的方式
- (void)useAccelerometerPull{
//判斷加速度計可不可用
if (self.manager.accelerometerAvailable){
//設定加速計多久取樣一次
self.manager.accelerometerUpdateInterval = 0.1;
//開始更新,後臺執行緒開始執行。這是Pull方式。
[self.manager startAccelerometerUpdates];
}
//獲取並處理加速度計資料。這裡我們就只是簡單的做了列印。
NSLog(@"X = %f,Y = %f,Z = %f",self.manager.accelerometerData.acceleration.x,self.manager.accelerometerData.acceleration.y,self.manager.accelerometerData.acceleration.z);
}
複製程式碼
3.2 PUSH的方式
- (void)useAccelerometerPush{
//判斷加速度計可不可用,判斷加速度計是否開啟
if (self.manager.accelerometerAvailable){
//設定加速計多久取樣一次
self.manager.accelerometerUpdateInterval = 0.1;
//Push方式獲取和處理資料,這裡我們一樣只是做了簡單的列印。把取樣的工作放在了主執行緒中。
[self.manager startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue]
withHandler:^(CMAccelerometerData *accelerometerData, NSError *error){
NSLog(@"X = %f,Y = %f,Z = %f",self.manager.accelerometerData.acceleration.x,self.manager.accelerometerData.acceleration.y,self.manager.accelerometerData.acceleration.z);
}];
} else{
NSLog(@"不可用");
}
}
複製程式碼
3.3 列印結果
我們可以愉快的看到XYZ軸的數值在瘋狂地變化。這中間我的手機螢幕一直在晃動。
4. 實現圖片永遠水平方向
4.1 思路
STEP1:為了能夠讓圖片無論在裝置如何傾斜的情況下都保持水平,肯定首先要獲取到螢幕的旋轉。
STEP2:用很高的頻率獲取到這個數值之後,來旋轉圖片。 STEP 3: 就結束了。神馬?!!!!開玩笑啦。其實在這個過程中可以發現,圖片在旋轉的時候會有一些抖動。腫麼辦呢?我們可以考對一定時間內獲取的資料取平均值來緩和。在使用了下次文章介紹的陀螺儀之後,抖動效果也會得到明顯的改善。這一部分的程式碼部分宅胖兒就沒有實現了,自己嘗試一下?!啦啦啦啦啦。
4.2 實現
- (void)keepBalance{
if (self.manager.accelerometerAvailable) {
//設定加速計取樣頻率
self.manager.accelerometerUpdateInterval = 0.01f;
[self.manager startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMAccelerometerData * _Nullable accelerometerData, NSError * _Nullable error) {
// 計算圖片的水平傾斜角度。這裡沒有實現Z軸的形變,所以我們們只能在XY軸上變換。有興趣的童鞋自己實現Z軸好不好?
double rotation = atan2(accelerometerData.acceleration.x, accelerometerData.acceleration.y) - M_PI;
self.imageView.transform = CGAffineTransformMakeRotation(rotation);
}];
}
}
複製程式碼
4.3 關於形變角度atan2的說明
//計算旋轉角度
double rotation = atan2(accelerometerData.acceleration.x, accelerometerData.acceleration.y) - M_PI;
複製程式碼
這個裡面用到了一個C語言的函式。atan2返回的是原點至點(x,y)的方位角,即與 x 軸的夾角。
你可能從未用過atan2這個函式,它和atan類似,但atan返回值範圍是(-PI/2,PI/2),atan2返回值範圍是(-PI,PI),並且他有兩個引數。
atan2這個函式我們其實可以在很多地方都看到,Android、JS、PHP等等都能遇見到。如果想進一步深入瞭解,可以移步百度百科,感覺講的還算挺清楚的。百度百科關於atan2的連結; 維基百科關於atan2的連結。
好啦~手工~~~下次我們們用陀螺儀做一個水平滾動的小球的遊戲玩玩~
多謝各位大爺評論、點贊、打賞。
原始碼下載地址:OC+Swift兩版。下載地址