某些偏门的 API 真是没有需求一辈子都不知道啊。

分享一下最近对于获取移动设备旋转方向的探索。

deviceorientation

window.addEventListener('deviceorientation', function(e){
console.log('absolute: ' + e.absolute)
console.log('alpha: ' + e.alpha)
console.log('beta: ' + e.beta)
console.log('gamma: ' + e.gamma)
});

之前在 segmentfault 回答过相关问题,当时是从 MDN 翻出了这个事件。

原贴:h5 页面如何获取手机陀螺仪的参数

该事件在移动端兼容较好:Android Webview 4.3+、Chrome for Android 5.0、iOS 8.4+,据我测试微信也是支持的。
没有在低端机上测试过,可能该事件会依赖设备传感器,可以加个 'ondeviceorientation' in window 判断一下。

该事件触发频率高,适合对设备旋转精度要求较高的场景或是 3d 场景等,比如上面问题中的平衡球。

orientationchange

当设备的方向改变时,触发该事件。

window.addEventListener("orientationchange", function() {
console.log('angle: ' + screen.orientation.angle);
});

该事件是基于 2d 平面角度触发,输出仅有 0、90、270 3个数值,可以用来知晓当前设备的手持方向。
至于为什么没有 360 这个角度,可能跟设备有关。我的手机怎么转都到不了 360 度,也就是竖屏时无法翻转。

触发这个事件需要设备开启屏幕旋转,或者叫屏幕锁定,不同的设备叫法不一样。

兼容性是个大问题,目前只发现手机上的 Chrome 可以使用,微信、iOS、以及一些双核国产浏览器都不兼容。

screen.orientation

通过上个事件让我发现了screen.orientation,在控制台输出后,发现它也有事件支持。

console.log(screen.orientation) // {angle: 0, type: "landscape-primary", onchange: null}
screen.orientation.onchange = function(){
console.log('angle: ' + screen.orientation.angle);
}

通过对该对象输出,发现也可以使用 screen.orientation.type 判断设备方向。

  • landscape-primary | landscape-secondary:横屏;
  • portrait-primary | portrait-secondary: 竖屏;
  • primary 表示向上或向右,secondary 表示向左或向下。

之后测试该事件,手机 Chrome 和国产双核浏览器通过,生产环境下使用还不够理想。

window.onresize

完全是灵机一动想到的,设备旋转会使屏幕宽高置换,自然就会触发 resize 事件。

window.onresize = function(){
console.log('innerWidth: ' + this.innerWidth + ' innerHeight: ' + this.innerHeight);
}

通过屏幕宽高比较来判断横屏还是竖屏,设备兼容度毋容置疑。

Media Queries

最后就是 css3 媒体查询了。

@media screen and (orientation: portrait){
/* 横屏 */
}
@media screen and (orientation: landscape){
/* 竖屏 */
}

如果仅仅是为了针对屏幕方向添加样式的话,使用媒体查询是最佳方案了。

移动端使用也没有兼容问题,媒体查询从 IE9 就开始支持了。

测试

Demo

测试Demo
测试Demo