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中必须通过用户操作去获取该权限
}