也许有人会问,
中都是竖直app形态,要横竖屏判断有什么用?即使判断出了横屏状态,你能把小程序横过来?答案是不能的,但是判断当前设备处于横屏或者竖屏状态来实现一些友好的用户体验交互方式的需求确实存在。例如手机横屏,让视频播放自动全屏,手机竖屏,让视频切换回来小屏。然而,截止至目前,小程序官方的API中并没有提供这样的横竖屏判断的方法。那么我们只能自己想办法实现这样的判断。小程序的设备API中提供了加速度计的监听方法,使用方法如下:
wx.onAccelerometerChange(function(res) {
console.log(res.x)
console.log(res.y)
console.log(res.z)
})
以下是一般移动设备的加速度计三轴坐标系示例图:
以手机竖直面向用户为例,加速计的三轴坐标系统的X、Y、Z轴定义如下:
当手机处于静止状态时,手机此时只受一个重力加速度(1g=9.8m/s²)的作用,加速度计返回的res.x、res.y、res.z的值就是设备的三轴受到的加速度的值,取值范围从[-1g,1g]。设备以不同方式放置时,x/y/z的值如下:
在stackoverflow上找到了根据加速度计三轴的值计算姿态角公式(https://stackoverflow.com/questions/3755059/3d-accelerometer-calculate-the-orientation),经过结合设备的三轴坐标方向对公式进行调整,最终得出了公式:
Pitch
=
atan2(Y,
Z)
*
180/M_PI;Roll
=
atan2(-X,
sqrt(Y*Y
+
Z*Z))
*
180/M_PI;
Roll
=
atan2(-X,
sqrt(Y*Y
+
Z*Z))
*
180/M_PI;
当设备绕着自身Y轴旋转时(表示手机左侧或右侧翘起的角度),该角度值将会发生变化,取值范围是-90到90度。
当手机绕着自身的Y轴旋转(表示手机顶部或尾部翘起的角度),该角度会发生变化,值的范围是-180到180度。
接下来就是根据自己对横竖屏角度的观测,再结合微信小程序中,视频全屏只能以手机向左旋转方式全屏的特性,只对用户左侧横屏判断为横屏状态,实现代码片段如下:
// 0为竖屏,1为横屏
let lastState = 0;
let lastTime = Date.now();
wx.startAccelerometer();
wx.onAccelerometerChange((res) => {
const now = Date.now();
// 500ms检测一次
if (now - lastTime < 500) {
return;
}
lastTime = now;
let nowState;
// 57.3 = 180 / Math.PI
const Roll = Math.atan2(-res.x, Math.sqrt(res.y * res.y + res.z * res.z)) * 57.3;
const Pitch = Math.atan2(res.y, res.z) * 57.3;
// console.log('Roll: ' + Roll, 'Pitch: ' + Pitch)
// 横屏状态
if (Roll > 50) {
if ((Pitch > -180 && Pitch < -60) || (Pitch > 130)) {
nowState = 1;
} else {
nowState = lastState;
}
} else if ((Roll > 0 && Roll < 30) || (Roll < 0 && Roll > -30)) {
let absPitch = Math.abs(Pitch);
// 如果手机平躺,保持原状态不变,40容错率
if ((absPitch > 140 || absPitch < 40)) {
nowState = lastState;
} else if (Pitch < 0) { /*收集竖向正立的情况*/
nowState = 0;
} else {
nowState = lastState;
}
}
else {
nowState = lastState;
}
// 状态变化时,触发
if (nowState !== lastState) {
lastState = nowState;
if (nowState === 1) {
console.log('change:横屏');
} else {
console.log('change:竖屏');
}
}
});
然后就可以在横竖屏切换的状态下,去切换视频的横竖屏了
if (state === 1) {
video.requestFullScreen();
} else {
video.exitFullScreen();
}