滴滴打車車輛轉彎的,歷史軌跡運動可能都需要這個功能吧.
頭幾天偶然看見了這個https://www.douban.com/group/topic/38478506/?author=1&start=0,作為程序員都身同感受吧,但是可惜沒找到下文,所以今天我們來完成這個功能
讓我指向像你
不想看我墨跡一些沒營養(yǎng)的下面有地址demo~~
實現(xiàn)思路
- 1 不管手機怎么移動,我的紅心手將指向你,所以這應該是一個指南針
- 2 但是我不想指向北方,所以我們之間和北極應該有個角度,找到這個角度,我就找到你了
- 3 應該還有個距離. 這個百度代碼很多~~~
好的,我們首先先做個指南針.
1.導入頭文件 #import <CoreLocation/CoreLocation.h>
這個框架
簽好協(xié)議<CLLocationManagerDelegate>
和私有屬性@property (nonatomic, strong) CLLocationManager *locationM;
2.然后懶加載
#pragma mark - 懶加載
- (CLLocationManager *)mgr
{
if (!_mgr) {
_mgr = [[CLLocationManager alloc] init];
}
return _mgr;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self.mgr startUpdatingHeading];
}
3.實現(xiàn)協(xié)議
// 當獲取到用戶方向時就會調用
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
/*
magneticHeading 設備與磁北的相對角度
trueHeading 設置與真北的相對角度, 必須和定位一起使用, iOS需要設置的位置來計算真北
真北始終指向地理北極點
*/
// 1.將獲取到的角度轉為弧度 = (角度 * π) / 180;
CGFloat angle = newHeading.magneticHeading * M_PI / 180;
// 2.旋轉圖片
/*
順時針 正
逆時針 負數(shù)
*/
// 因為如果沒有動畫的話旋轉的時候回出現(xiàn)卡頓的現(xiàn)象,為了更流暢,我們給它加個動畫
[UIView animateWithDuration:0.1 animations:^{
// 旋轉圖片
self.compasspointer.transform = CGAffineTransformMakeRotation(-a);
}];
}
這個協(xié)議方法是一直調用的,不信你打印一下試試,所以最好不要在這里寫任何耗時的事,self.compasspointer
是一個圖片,這里為了減少資源損耗就不畫圓了,用圖片是一樣的.
- 這樣就是一個正經八經的指南針了.下面只要求出來我們之間的角度,就完成了.
好的,我們找角度
1.根據百度的坐標提取系統(tǒng)我們可以知道任意兩個點之間的坐標
//我在大連的
float lat1 = 38.927431;
float lng1 = 121.650592;
// 這是北京(假設就是北京)往下一點 116.650592,38.927431
float lat2 = 38.927431;
float lng2 = 116.650592;
2. 求出兩個經緯度之間的角度
//兩個經緯度之間的角度
-(double)getBearingWithLat1:(double)lat1 whitLng1:(double)lng1 whitLat2:(double)lat2 whitLng2:(double)lng2{
double d = 0;
double radLat1 = [self radian:lat1];
double radLat2 = [self radian:lat2];
double radLng1 = [self radian:lng1];
double radLng2 = [self radian:lng2];
d = sin(radLat1)*sin(radLat2)+cos(radLat1)*cos(radLat2)*cos(radLng2-radLng1);
d = sqrt(1-d*d);
d = cos(radLat2)*sin(radLng2-radLng1)/d;
d = [self angle:asin(d)];
return d;
}
//根據角度計算弧度
-(double)radian:(double)d{
return d * M_PI/180.0;
}
//根據弧度計算角度
-(double)angle:(double)r{
return r * 180/M_PI;
}
我們緯度是一樣的,根據上面的公式求出 北京 大連 北極之間的角度
3 why? 口算都算出來了,應該是九十度啊?這怎么事八十八度?還是負數(shù)?后來我百度了一下真北,磁北,坐標北 ,我就不管這點誤差了,當然這是可以處理的.
負數(shù)的問題,取個絕對值就好了,先不管這多為啥是負數(shù)好了,變正數(shù)了,正數(shù)也可以一個人一個做法,不要吐槽我~
4 接下來為了驗證正確性,我們把坐標改成山東東營,
// 獲取地理位置坐標的代碼就不貼了,我在大連中山廣場, 這是我的坐標 121.650592,38.927431
float lat1 = 38.927431;
float lng1 = 121.650592;
// 山東 東營
float lat2 = 37.588364;
float lng2 = 118.593547;
按地圖上來看角度應該是一百多度吧,但是打印出來的結果是
2018-04-20 17:14:06.029517+0800 angle[3667:1273780] -61.798896
2018-04-20 17:14:06.029610+0800 angle[3667:1273780] 61.798896
所以我又寫了兩行代碼
if(lat2 < lat1){
s = 180-s;
}
這回打印結果
2018-04-20 17:14:06.029637+0800 angle[3667:1273780] 118.201104
好像對上
但是旋轉圖片的
self.compasspointer.transform = CGAffineTransformMakeRotation(-a);
-a 是根據弧度計算的,值是0 到 2*π, 這個"我指向你的角度"就是 a弧度減去我求出來的角度
//宏定義
#define DEGREES_TO_RADIANS(angle) ( M_PI / 180 * (angle))
self.f = DEGREES_TO_RADIANS(s);
if (lng2 < lng1) {
_f = (M_PI*2 - _f);
}
打印出來2018-04-20 17:14:06.029687+0800 angle[3667:1273780] 4.220187
最后
// 當獲取到用戶方向時就會調用
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
/*
magneticHeading 設備與磁北的相對角度
trueHeading 設置與真北的相對角度, 必須和定位一起使用, iOS需要設置的位置來計算真北
真北始終指向地理北極點
*/
// 1.將獲取到的角度轉為弧度 = (角度 * π) / 180;
CGFloat angle = newHeading.magneticHeading * M_PI / 180;
// 2.旋轉圖片
/*
順時針 正
逆時針 負數(shù)
*/
CGFloat a = 0;
a = angle - _f;
// 因為如果沒有動畫的話旋轉的時候回出現(xiàn)卡頓的現(xiàn)象,為了更流暢,我們給它加個動畫
[UIView animateWithDuration:0.1 animations:^{
// 旋轉圖片
self.compasspointer.transform = CGAffineTransformMakeRotation(-a);
}];
}
效果圖
墨跡完了,我也不知道我做的對不對,有問題一起探討
下面是項目地址
demo (記得用真機)
Xcode9.3 以下打開會有問題???