JavaScript 陀螺儀檢測設備方向(重力感應)

隨着陀螺儀做爲只能手機的標配,根據手機角度不一樣,讓圖片有點視差微動效果能夠給用戶一點驚喜,因而簡單研究了一下 HTML5 下利用陀螺儀獲取設備方向的 API。javascript

處理方向變化的事件

HTML5 中與手機方向變化有關的 API 有兩個,一個是 deviceorientation 事件,一個是 devicemotion 事件。 css

今天這個根據手機動來動去產生微動效果的主要用到 deviceorientation 事件,這個事件主要是監聽並接收設備方向變化信息。
devicemotion 事件主要是用來監聽設備在位置和方向上的加速度變化信息,這個主要用在搖一搖等應用上。html

監聽 deviceorientation 事件比較簡單: java

window.addEventListener('deviceorientation', handleFunc, false);複製代碼

而後在回調函數 handleFunc 中會有設備轉過的角度:android

function handleFunc(evnet){
    var alpha = event.alpha;
    var beta = event.beta;
    var gamma = event.gamma;
 }複製代碼

這裏的 alpha, beta, gamma 表示的是相對於座標軸,設備在某個給定軸上的旋轉量。ios

  • alpha:表示設備沿 Z 軸旋轉的角度,範圍爲 0~360;
  • beta:表示設備在x軸上的旋轉角度,範圍爲-180~180。它描述的是設備由前向後旋轉的狀況;
  • gamma:表示設備在y軸上的旋轉角度,範圍爲-90~90。它描述的是設備由左向右旋轉的狀況。

另外放上座標系的圖,方便理解:git

光是這樣看可能不太好理解,咱們能夠打開 chrome 開發者工具 Sensors 這一項看看直觀的感覺。程序員

當咱們手機出於直立狀態的時候:github

也就是隻有 beta 值是 90,其它兩個都是 0,能夠本身改下 beta 值,體驗下什麼叫沿 X 軸轉。web

一樣的,沿着 Z 軸轉的 alpha 值,就是相似咱們豎着轉手機。


gamma 值:

這樣大概就能理解這三個屬性是表示些什麼東西了,可是這幾個值麻煩的地方是,並不能經過單單一個值來表示出手機向某個方向運動,運動的方向還和手機放置的位置有很大關係。除此以外,還有一個坑是 android 中陀螺儀的數據自己不是很穩定,通常不能直接使用,須要加一些緩衝之類的方法來降噪。

還好,上面那些坑已經有人開始填了,就是 shrekwang 大大作的orienter 組件

orienter 組件

orienter 組件除了提供上面說到的 alpha,beta,gamma 值以外,還另外提供了兩個計算出來的值,分別是 lon 和 lat,字面意思是經度,緯度,能夠大體用來當成平移距離來計算。

咱們來簡單寫個小 demo,隨着手機動,圖片也有一些視差效果,原理是利用 deviceorientation 事件來獲取手機運動方向的改變,而後經過 transform:translate3d(x,y,z) 給設置到圖片上。

首先是 html:

<div class="content">
        <img src="../img/test.jpg" class="img"> </div>複製代碼

HTML 比較簡單,咱們只是放個圖片上去。

而後是利用 orienter 組件來實現咱們的功能。

var o = new Orienter();
      o.onOrient = function (obj) {
        var a, b;

        a = obj.lon < 180 ? obj.lon : obj.lon - 360;
        b = obj.lat;

        a = a > 0 ? a > 50 ? 50 : a : a < -50 ? -50 : a;
        b = b > 0 ? b > 50 ? 50 : b : b < -50 ? -50 : b;

        $(".img").css("-webkit-transform", "translate3d(" + a + "px," + b + "px,0)");

      };
      o.init();複製代碼

代碼比較簡單,其中咱們對 lon 值進行了處理,lon 的取值範圍是 0~360,其中,小於 180 的咱們認爲是往右移,大於 180 的當成是往左邊移動,往左的咱們要計算出一個負值。

而後下面有一堆三元運算符用來作判斷,由於咱們平移的距離有一個極限,這裏我設置的是 50。

放上體驗地址:www.imbeta.cn/demo/demos/…

PC 上記得打開 chrome 模擬手機和試試在 Sensors 裏模擬轉向。

orienter 代碼

最後,orienter 幫咱們作了那麼多事情,固然要大概看下它的源代碼啦。

首先是前面一段是兼容 AMD & CMD 和普通引入的代碼:

(function (factory) {

    if (typeof define === 'function' && define.amd) {
        define(['exports'], function(exports) {
            window.Orienter = factory(exports);
        });
    } else if (typeof exports !== 'undefined') {
        factory(exports);
    } else {
        window.Orienter = factory({});
    }

}(function (Orienter) {
    ……
    ……
}複製代碼

以後最重點的是 _orient 方法,其中有個 switch,就是處理咱們上面說的 lon 和 lat 兩個值的計算,還有運動的方向還和手機放置的位置的處理,以及對 android 陀螺儀不穩定的處理。

代碼以下:

switch (this.os) {
                case 'ios':
                    switch (this.direction) {
                        case 0:
                            this.lon = event.alpha + event.gamma;
                            if (event.beta > 0) this.lat = event.beta - 90;
                            break;
                        case 90:
                            if (event.gamma < 0) {
                                this.lon = event.alpha - 90;
                            } else {
                                this.lon = event.alpha - 270;
                            }
                            if (event.gamma > 0) {
                                this.lat = 90 - event.gamma;
                            } else {
                                this.lat = -90 - event.gamma;
                            }
                            break;
                        case -90:
                            if (event.gamma < 0) {
                                this.lon = event.alpha - 90;
                            } else {
                                this.lon = event.alpha - 270;
                            }
                            if (event.gamma < 0) {
                                this.lat = 90 + event.gamma;
                            } else {
                                this.lat = -90 + event.gamma;
                            }
                            break;
                    }
                    break;
                case 'android':
                    switch (this.direction) {
                        case 0:
                            this.lon = event.alpha + event.gamma + 30;
                            if (event.gamma > 90) {
                                this.lat = 90 - event.beta;
                            } else {
                                this.lat = event.beta - 90;
                            }
                            break;
                        case 90:
                            this.lon = event.alpha - 230;
                            if (event.gamma > 0) {
                                this.lat = 270 - event.gamma;
                            } else {
                                this.lat = -90 - event.gamma;
                            }
                            break;
                        case -90:
                            this.lon = event.alpha - 180;
                            this.lat = -90 + event.gamma;
                            break;
                    }
                    break;
            }複製代碼

分別根據 ios/android 平臺對豎屏和左右橫屏作相應處理。

咱們來看下 ios 下的豎屏:

case 0:
               this.lon = event.alpha + event.gamma;
               if (event.beta > 0) this.lat = event.beta - 90;
               break;複製代碼

先看下面那句處理 lat 的,if (event.beta > 0) this.lat = event.beta - 90; 這裏 -90 就是由於豎屏的時候,beta 值默認爲 90。即下面這個圖:

因此這裏 -90 比較好理解。

而後再看上面那句 this.lon = event.alpha + event.gamma; 這裏我想了很久,也沒想出來爲何豎屏的時候 lon 的值是 alpha 和 gamma 之和。

要理解這個,要從咱們日常使用手機的動做來看。現看 gamma 值,gamma 是沿着 y 軸轉動,拿出手機,豎直放置,沿着 y 軸轉一下,手機是這樣的狀態:

這樣的時候咱們通常是要看到更多的左右信息,也就是橫向的經度值,因此手機豎直的時候 gamma 要算到 lon 裏面。

再來看 alpha 值,alpha 值是表示設備沿 Z 軸的變化。要理解這個,咱們要試着想象咱們在拍全景照片。以本身爲圓心,手臂與地面平行,豎着拿着手機,手臂做爲半徑,嘗試像拍攝全景照片,以身體爲圓心,移動手臂。會發現咱們咱們實際上是在作一個圓,而在這途中,手機實際上是沿着 Z 軸在轉動的。

若是以爲說的太抽象,能夠看看下面這個例子,嘗試理解一下。

shrek.imdevsh.com/demo/kfc/

二維碼:

結語

不少看起來很容易實現的功能,實際上卻有不少不少的坑,要填這些坑,又要有不少積累和思考,對於那些幫你填坑的人,要說一聲『謝謝』。

Demo 源碼地址:github.com/bob-chen/de…

碎碎念

記錄一些所思所想,寫寫科技與人文,寫寫生活狀態,寫寫讀書感悟,主要是扯淡和感悟,歡迎關注,交流。

微信公衆號:程序員的詩和遠方

公衆號ID : MonkeyCoder-Life

參考連接

developers.google.com/web/fundame…

www.w3.org/html/ig/zh/…

developer.mozilla.org/zh-CN/docs/…

github.com/shrekshrek/…

相關文章
相關標籤/搜索