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/…

相关文章
相关标签/搜索