摇一摇事件 DeviceOrientation 和 DeviceMotion

起因

在做大屏幕项目时,与用户互动部分包括摇一摇功能,但发现页面中摇一摇在手机上无效,怎么调试都不管用。查了半天资料才清楚其原因,于是记录下来。

设备方向和运动监听

html 5 提供了一些方法在移动端获得设备方向及运动(因为他是依赖传感器硬件的,pc没有也不存在抱着台式机跑来跑去场景)。传感器包括陀螺仪、加速器和磁力仪(罗盘)

DeviceMotionEvent 事件

在设备发生摆动、运动(手机疯狂摇摆,摇一摇场景)时产生。是用来监听手机加速度变化的事件回调中可以提供设备的加速度信息。
表示为在设备上定义的坐标系中的笛卡尔坐标,提供了设备在坐标系中的自转速率。

有四个只读属性:

  • accelerationIncludingGravity:设备在 X,Y,Z 轴方向上带重力的加速度的对象。加速度的单位为 m/s²。重力加速度(包括重心引力)
  • acceleration:设备在 X, Y, Z 轴方向上加速度的对象。加速度的单位为 m/s²。加速度(需要设备陀螺仪支持)
  • rotationRate:设备在 alpha,beta, gamma 轴方向上旋转的速率的对象。旋转速率的单位为 °/s(degrees per seconds) 。旋转速度
  • interval:表示从设备获取数据的频率,单位是毫秒。获取的时间间隔

DeviceOrientationEvent 事件

加速度传感器检测到设备在方向上产生变化时触发。监听设备方向(设备旋转和仰角变化的行为),提供设备的物理方向信息,表示为一系列本地坐标系的旋角。

有三个只读属性:

  • alpha
  • beta
  • gamma

如何判断手机是否在摇动

在手机测试时,我们发现其值变化非常灵敏,手机稍微动一下两个事件的值都会变化。我们可以定义各种属性变化是否超过阀值,超过表示在摇动,否则未被摇动

踩坑记录

  • 重力感应需要使用 https 协议,http下不工作
  • 在IOS13+系统,苹果为了手机的安全性,导致重力感应需要用户主动进行触发后才可以正常使用
//原生js监听陀螺仪事件
​​​​if (window.DeviceMotionEvent) {
    window.addEventListener('devicemotion', function () {
        var acceleration = event.accelerationIncludingGravity;
        var x = acceleration.x;
        var y = acceleration.y;
        var z = acceleration.z;
        // you can do something
    }, false);
}
# 授权优化后的代码
DeviceMotionEvent.requestPermission().then(function (state) {
    if ('granted' === state) {
       window.addEventListener('devicemotion', function () {
           // you can do something
       }, false);
    } else {
        alert('apply permission state: ' + state);
    }
}).catch(function(err){
    alert('error: ' + err);
});
# 完整的代码,在入口文件中就让其同意授权即可
<link rel="stylesheet" href="template/app/css/weui.min.css">
<link rel="stylesheet" href="template/app/css/jquery-weui.min.css">

<script type="text/javascript" src="template/app/js/jquery-2.1.4.js"></script>
<script type="text/javascript" src="template/app/js/jquery-weui.min.js"></script>

$(function(){
    //$.alert("测试弹窗");
    permission();
});

function permission() {
    var ua = navigator.userAgent.toLowerCase();
    if (ua.indexOf("like mac os x") > 0) {
        var reg = /os [\d._]*/gi;
        var verinfo = ua.match(reg);
        var version = (verinfo + "").replace(/[^0-9|_.]/ig, "").replace(/_/ig, ".");
        var arr = version.split(".");
        if (arr[0] > 13) {  //对13以后的版本处理,
            DeviceMotionEvent.requestPermission().then(permissionState => {
                if (permissionState === "granted") {
                    $.alert("你授权了,可以进行摇一摇");
                }
                if (permissionState === "denied") {
                    $.alert("你拒绝了,摇一摇功能失效");
                }
            }).catch((err) => {
                //======这里可以防止重复授权,因为获取权限需要点击事件才能触发===//
                $.alert({
                    title: '获取授权',
                    text: '允许授权才能参加活动',
                    onOK: function () {
                        reqShakePermission();
                    }
                });
            });
        } else {
            // 13以前的版本不用授权

        }
    } else {
        // 非苹果系统不用授权

    }
}

function reqShakePermission() {
    if (typeof window.DeviceMotionEvent !== 'undefined' && typeof window.DeviceMotionEvent.requestPermission === 'function') {
        DeviceMotionEvent.requestPermission().then((permissionState) => {
            if (permissionState === "granted") {
                $.alert("您同意了摇一摇功能授权");
            } else if (permissionState == "denied") {
                $.alert("您拒绝了摇一摇功能授权");
            }
        }).catch((error) => {
            // console.log(error);
        });
    } else {
        // 处理常规的非iOS 13+设备
        // console.log("处理常规的非iOS 13+设备");
        if (window.DeviceMotionEvent) {
            $.alert("可以进行摇一摇");
        } else {
            // console.log('不支持window.DeviceMotionEvent');
        }
    }
}

测试地址

此处评论已关闭