滴滴打車車輛轉(zhuǎn)彎的,歷史軌跡運(yùn)動(dòng)可能都需要這個(gè)功能吧.
頭幾天偶然看見了這個(gè)https://www.douban.com/group/topic/38478506/?author=1&start=0,作為程序員都身同感受吧,但是可惜沒找到下文,所以今天我們來完成這個(gè)功能
讓我指向像你

不想看我墨跡一些沒營養(yǎng)的下面有地址demo~~
實(shí)現(xiàn)思路
- 1 不管手機(jī)怎么移動(dòng),我的紅心手將指向你,所以這應(yīng)該是一個(gè)指南針
- 2 但是我不想指向北方,所以我們之間和北極應(yīng)該有個(gè)角度,找到這個(gè)角度,我就找到你了
- 3 應(yīng)該還有個(gè)距離. 這個(gè)百度代碼很多~~~
好的,我們首先先做個(gè)指南針.
1.導(dǎo)入頭文件 #import <CoreLocation/CoreLocation.h>這個(gè)框架
簽好協(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.實(shí)現(xiàn)協(xié)議
// 當(dāng)獲取到用戶方向時(shí)就會(huì)調(diào)用
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
/*
magneticHeading 設(shè)備與磁北的相對(duì)角度
trueHeading 設(shè)置與真北的相對(duì)角度, 必須和定位一起使用, iOS需要設(shè)置的位置來計(jì)算真北
真北始終指向地理北極點(diǎn)
*/
// 1.將獲取到的角度轉(zhuǎn)為弧度 = (角度 * π) / 180;
CGFloat angle = newHeading.magneticHeading * M_PI / 180;
// 2.旋轉(zhuǎn)圖片
/*
順時(shí)針 正
逆時(shí)針 負(fù)數(shù)
*/
// 因?yàn)槿绻麤]有動(dòng)畫的話旋轉(zhuǎn)的時(shí)候回出現(xiàn)卡頓的現(xiàn)象,為了更流暢,我們給它加個(gè)動(dòng)畫
[UIView animateWithDuration:0.1 animations:^{
// 旋轉(zhuǎn)圖片
self.compasspointer.transform = CGAffineTransformMakeRotation(-a);
}];
}
這個(gè)協(xié)議方法是一直調(diào)用的,不信你打印一下試試,所以最好不要在這里寫任何耗時(shí)的事,self.compasspointer是一個(gè)圖片,這里為了減少資源損耗就不畫圓了,用圖片是一樣的.
- 這樣就是一個(gè)正經(jīng)八經(jīng)的指南針了.下面只要求出來我們之間的角度,就完成了.
好的,我們找角度
1.根據(jù)百度的坐標(biāo)提取系統(tǒng)我們可以知道任意兩個(gè)點(diǎn)之間的坐標(biāo)
//我在大連的
float lat1 = 38.927431;
float lng1 = 121.650592;
// 這是北京(假設(shè)就是北京)往下一點(diǎn) 116.650592,38.927431
float lat2 = 38.927431;
float lng2 = 116.650592;
2. 求出兩個(gè)經(jīng)緯度之間的角度
//兩個(gè)經(jīng)緯度之間的角度
-(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;
}
//根據(jù)角度計(jì)算弧度
-(double)radian:(double)d{
return d * M_PI/180.0;
}
//根據(jù)弧度計(jì)算角度
-(double)angle:(double)r{
return r * 180/M_PI;
}
我們緯度是一樣的,根據(jù)上面的公式求出 北京 大連 北極之間的角度

3 why? 口算都算出來了,應(yīng)該是九十度啊?這怎么事八十八度?還是負(fù)數(shù)?后來我百度了一下真北,磁北,坐標(biāo)北 ,我就不管這點(diǎn)誤差了,當(dāng)然這是可以處理的.
負(fù)數(shù)的問題,取個(gè)絕對(duì)值就好了,先不管這多為啥是負(fù)數(shù)
好了,變正數(shù)了,正數(shù)也可以一個(gè)人一個(gè)做法,不要吐槽我~
4 接下來為了驗(yàn)證正確性,我們把坐標(biāo)改成山東東營,
// 獲取地理位置坐標(biāo)的代碼就不貼了,我在大連中山廣場(chǎng), 這是我的坐標(biāo) 121.650592,38.927431
float lat1 = 38.927431;
float lng1 = 121.650592;
// 山東 東營
float lat2 = 37.588364;
float lng2 = 118.593547;
按地圖上來看角度應(yīng)該是一百多度吧,但是打印出來的結(jié)果是
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;
}
這回打印結(jié)果
2018-04-20 17:14:06.029637+0800 angle[3667:1273780] 118.201104
好像對(duì)上
但是旋轉(zhuǎn)圖片的
self.compasspointer.transform = CGAffineTransformMakeRotation(-a);
-a 是根據(jù)弧度計(jì)算的,值是0 到 2*π, 這個(gè)"我指向你的角度"就是 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
最后
// 當(dāng)獲取到用戶方向時(shí)就會(huì)調(diào)用
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
/*
magneticHeading 設(shè)備與磁北的相對(duì)角度
trueHeading 設(shè)置與真北的相對(duì)角度, 必須和定位一起使用, iOS需要設(shè)置的位置來計(jì)算真北
真北始終指向地理北極點(diǎn)
*/
// 1.將獲取到的角度轉(zhuǎn)為弧度 = (角度 * π) / 180;
CGFloat angle = newHeading.magneticHeading * M_PI / 180;
// 2.旋轉(zhuǎn)圖片
/*
順時(shí)針 正
逆時(shí)針 負(fù)數(shù)
*/
CGFloat a = 0;
a = angle - _f;
// 因?yàn)槿绻麤]有動(dòng)畫的話旋轉(zhuǎn)的時(shí)候回出現(xiàn)卡頓的現(xiàn)象,為了更流暢,我們給它加個(gè)動(dòng)畫
[UIView animateWithDuration:0.1 animations:^{
// 旋轉(zhuǎn)圖片
self.compasspointer.transform = CGAffineTransformMakeRotation(-a);
}];
}
效果圖


墨跡完了,我也不知道我做的對(duì)不對(duì),有問題一起探討
下面是項(xiàng)目地址
demo (記得用真機(jī))
Xcode9.3 以下打開會(huì)有問題???