DeviceMotion是什么?
window对象有一个事件DeviceMotionEvent,这个事件可以用来监听设备的加速度变化等信息,在该事件的event对象中,包含了acceleration对象,我们可以在acceleration对象中获取到设备在各方向上的加速度
问题:window.DeviceMotionEvent 有定义,但是无法触发
用法
if (window.DeviceMotionEvent) {
  window.addEventListener('devicemotion', function (e) {
    var acceleration = e.accelerationIncludingGravity
    // x,z,y分别对应手机三个方向的加速度
    // 需要注意的是,ios这三个值和安卓正好相反,比如我们向左移动手机,安卓会得到一个速度为10的x轴加速度,而ios会得到-10
    var x = acceleration.x
    var y = acceleration.y
    var z = acceleration.z
    // 。。。。
  })
}
踩坑:
1.ios 下的 https 要求
ios10 之后做了安全限制,要使用 devicemotion 必须使用 https 协议
2.ios12.2 之后的安全限制
ios12.2 之后,用户可以在手机的设置中关闭掉“动作与方向访问”,我们无法直接获取到用户是否关闭了这个权限的
3.ios13 的用户权限请求
ios13 以后需要用户申请权限,注意ios13.3以后要用户主动触发之后调用 DeviceMotionEvent.requestPermission(),不能打开页面是自动调用,否则会报错
[文档]<!https://w3c.github.io/deviceorientation/#devicemotionevent>
最终实现
// 判断是否是 ios 设备
function getIos() {
  var u = window.navigator.userAgent
  return !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
}
/*
setDeviceMotion 添加陀螺仪监控
cb devicemotion的事件处理函数
errCb 不支持 devicemotion 时的处理回调
*/
function setDeviceMotion(cb, errCb) {
  if (!window.DeviceMotionEvent) {
    errCb('设备不支持DeviceMotion')
    return
  }
  if (typeof DeviceMotionEvent.requestPermission === 'function') {
    // IOS 13
    DeviceMotionEvent.requestPermission()
      .then((permissionState) => {
        if (permissionState === 'granted') {
          window.addEventListener('devicemotion', cb)
        }
      })
      .catch((err) => {
        errCb('用户未允许权限')
      })
  } else {
    // 其他支持加速度检测的系统
    let timer = setTimeout(function () {
      errCb('用户未开启权限')
    }, 1000)
    window.addEventListener(
      'devicemotion',
      (e) => {
        clearTimeout(timer)
      },
      { once: true }
    )
    window.addEventListener('devicemotion', cb)
  }
}
document.ontouchstart = function () {
  setDeviceMotion(
    (e) => {
      let motion = e.acceleration
      let { x, y, z } = motion
      if (!getIos()) {
        x = -x
        y = -y
        z = -z
      }
    },
    (errMessage) => {
      alert(errMessage)
    }
  ) // 最后这里一定要注意,在IOS 13.3中必须通过用户操作去获取该权限
}