羅盤,估計也不用我過多介紹,學過初中物理的都知道,不論是指南針,仍是指北針,其本質就是用來辨別方向的。async
操做電子羅盤偉感器也不復雜,主要就是兩個角度:ide
一、當前方向與磁北的夾角;spa
二、當前方向與地北的夾角。指針
同時,咱們也瞭解到,地理北極與地磁北極並非重合的,存在地偏角。在讀取電子羅盤數據時,能夠優先考慮讀取與地北極的夾角,若是讀不到地北極的夾角,再讀取磁北極的夾角數據。code
CompassReading類(位於Windows.Devices.Sensors命名空間)封裝了從電子羅盤所讀到的數據。orm
一、HeadingMagneticNorth屬性:獲取當前方向與磁北的夾角度數。對象
二、HeadingTrueNorth屬性:該屬性獲取的是真北夾角,即地理夾角。咱們注意到它的類型爲double?,即Nullable<double>,代表這個數值有可能爲null,也就是說有可能獲取不到地北夾角的值。在使用時,咱們能夠先判斷地北角是否爲null,如不爲null就用這個值;若是爲null就用磁北角的值。blog
三、HeadingAccuracy屬性:表示羅盤讀數的準確性,若是讀數精度較高,其返回High。咱們的應用程序能夠在合適的時候檢查這個屬性是否爲High,若是不是,能夠考慮提示用戶校準羅盤。事件
提到校準,不得不說一下的是,校準羅盤是不須要系統提示,應用也能夠不提示。只是考慮到用戶體驗的問題,能夠提示用戶校準。校準方法很簡單,無論你是使用WP自帶的地圖應用,仍是其餘第三方應用,或者你本身開發的應用。只要在使用到羅盤的地方,你拿着手機,在空中作幾回「8」字形來回移動就能夠了,不須要等待提示,只要在用到羅盤的地方就能夠隨時校準。ip
電子羅盤的API封裝在Windows.Devices.Sensors.Compass類中,WP API中的全部傳感器調用都很簡單,首先獲取到某個傳感器類的實例,通常經過GetDefault方法(靜態方法)就能返回,而後設置讀取的時間間隔,以毫秒爲單位,若是你但願每秒讀一次數據,就把ReportInterval設置爲1000,可是,這個時間間隔不能小於MinimumReportInterval屬性指定的值,這個要注意,設置爲20毫秒以上的間隔,效果都不錯了,固然這要看你使用的實際狀況了。
最後處理ReadingChanged事件,當有新的數據讀到時,會引起該事件,並把新讀到的數據傳遞給該事件,咱們就能夠從事件參數中獲取最新的讀數。
好了,理論永遠都是抽象的,下面給你們看一下我作的一個簡陋指南針,確實很簡,但願你們莫笑,由於本人較菜,因此連主頁上的羅盤也是用XAML直接畫的。
先上一個效果圖。
看吧,簡陋吧,沒辦法,人窮就是這樣,要簡食素衣。指南針背景我是用幾個圈圈畫的,指示方向的指針是用Path元素畫的。
原理是這樣的:
根據電子羅盤讀到的角度,對紅色的指針對象進行旋轉變換——就是用RotateTransform類來旋轉。但要注意旋轉的角度。好比,我當前方向是20度,即東北偏北方向,那麼,要怎麼設置角度才能保證紅色的指針始終指向南方呢。
咱們知道,夾角是以正北爲參考的,若是要使指針指向南方,一種方法是將羅盤讀到的角度加上180,由於南北的夾角正好是180度(平角);另外一種方法是,讓指針的初始位置向下,即指向正南方,我就是用這個方法的。如圖。
不論是指向北方仍是南方(上北下南),均可以按相同的角度來旋轉,由於它們的夾角正好是180。
因而,第二個問題產生了——要旋轉多少度才合適?咱們上面舉例說當前方向爲20度,參照標準是北極,也就是說此時咱們的手機已經偏向20度方向,若是把指針旋轉20度,那麼指針相對於屏幕,偏轉的角度就是40度了,原本就偏了20度,你再轉20度,就番倍了,顯然這樣不妥,咱們必須把這個角度差抵消掉。
也就是說,若是我當前方向是20度,那麼指針的旋轉變換應爲-20度,這樣才能把誤差的角度補平,否則的話,你試試就知道了,若是不抵消的話,指針會越走越偏。
還有一種方法就是用360度做爲被減數,如360 - 20 = 340度,-20度和340度雖然計算方向不一樣,但它們的位置是相同的。所以兩種方法均可以。好比讀數是80度,能夠把指針旋轉-80度,也能夠旋轉360 - 80度。
async void _compass_ReadingChanged ( Compass sender, CompassReadingChangedEventArgs args ) { var res = args.Reading; // 若是地北極的偏角值不可用,則使用磁北極角度 double val = res.HeadingTrueNorth ?? res.HeadingMagneticNorth; await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { // 若是精度較高,則中止校準 if (isChecking && res.HeadingAccuracy == MagnetometerAccuracy.High) { fly.Hide(); isChecking = false; } // 旋轉的方向是羅盤角度的負值 rotatTransform.Angle = -val; Display(val); }); }
Display方法是我自定義的方法,用來判斷讀數所指的方向,並在頁面上以文本的方式顯示。好比,讀數爲0,就是「正北」,讀數爲180度,爲「正南」等。
/// <summary> /// 顯示方位 /// </summary> private void Display ( double v ) { string d = ""; int ind = Convert.ToInt32(v); if (ind == 0 || ind == 360) { d = "正北"; } else if (ind == 90) { d = "正東"; } else if (ind == 180) { d = "正南"; } else if (ind == 270) { d = "正西"; } else if (ind > 0 && ind < 90) { d = "東北"; } else if (ind > 90 && ind < 180) { d = "東南"; } else if (ind > 180 && ind < 270) { d = "西南"; } else if (ind > 270 && ind < 360) { d = "西北"; } tbW.Text = string.Format("{0}°({1})", ind, d); }
以上所列是重點的代碼片斷,其餘代碼你們能夠參考我上傳的示例源代碼。