更靠谱的移动端横竖屏检测方法

前不久,做了一个H5项目,需要在横竖屏变化时,做一些处理。毫无疑问,需要使用orientationchange来监听横竖屏的变化。

方案一:


  1. // 监听 orientation changes 
  2. window.addEventListener("orientationchange", function(event) { 
  3.     // 根据event.orientation|screen.orientation.angle等于0|180、90|-90度来判断横竖屏 
  4. }, false);  

代码添加上后,就各种兼容性问题。这里兼容性问题出现在两个地方:

  • orientationchange
  • event.orientation|screen.orientation.angle

如下是orientationchange事件的兼容性:

如下是screen.orientation的兼容性:

方案二:

上述方案不行,只能另行他法了。google一下,了解到可以通过resize配合(window.inner/outerWidth, window.inner/outerHeight)来实现:


  1. window.addEventListener("resize", function(event) { 
  2.     var orientation=(window.innerWidth > window.innerHeight)? "landscape":"portrait"; 
  3.     if(oritentation === 'portrait'){ 
  4.         // do something …… 
  5.     } else { 
  6.         // do something else …… 
  7.     } 
  8. }, false);  

这种方案基本满足大部分项目的需求,但是还是有些不足之处:

  • 只要window的size变化,就会不断触发触发resize事件。可以使用setTimeout来优化一下
  • 如果有多个地方需要监听横竖屏,就需要注册多个window.addEventListener("resize", function(event) {……})。能不能通过订阅与发布模式来改进一下,只注册一个resize负责监听横竖屏变化,只要横竖发生变化就发布通知订阅的对象。其他需要监听横竖屏的地方只需订阅一下即可。

关键代码如下:


  1. var resizeCB = function(){ 
  2.      if(win.innerWidth > win.innerHeight){//初始化判断 
  3.        meta.init = 'landscape'; 
  4.        meta.current = 'landscape'; 
  5.      } else { 
  6.        meta.init = 'portrait'; 
  7.        meta.current = 'portrait'; 
  8.      } 
  9.      return function(){ 
  10.        if(win.innerWidth > win.innerHeight){ 
  11.          if(meta.current !== 'landscape'){ 
  12.            meta.current = 'landscape'; 
  13.            event.trigger('__orientationChange__', meta); 
  14.          } 
  15.        } else { 
  16.          if(meta.current !== 'portrait'){ 
  17.            meta.current = 'portrait'; 
  18.            event.trigger('__orientationChange__', meta); 
  19.          } 
  20.        } 
  21.      } 
  22.    }();  

完整代码猛击这里

方案三:

不过个人觉得通过window.innerWidth > window.innerHeight来实现的是一种伪检测,有点不可靠。 可不可以通过浏览器来实现检测?如基于CSS3@media媒体查询来实现。

如下@media兼容性:

如上上图所示,移动端浏览器都支持CSS3 media。

实现思路:

  • 创建包含标识横竖屏状态的特定css样式
  • 通过JS向页面中注入CSS代码
  • resize回调函数中获取横竖屏的状态

这里我选择<html></html>的节点font-family作为检测样式属性。理由如下:

  • 选择<html></html>主要为了避免reflow和repaint
  • 选择font-family样式,主要是因为font-family有如下特性:

1.优先使用排在前面的字体。

2.如果找不到该种字体,或者该种字体不包括所要渲染的文字,则使用下一种字体。

3.如果所列出的字体,都无法满足需要,则让操作系统自行决定使用哪种字体。

这样我们就可以指定特定标识来标识横竖屏的状态,不过需要将指定的标识放置在其他字体的前面,这样就不会引起hmtl字体的变化。

关键代码如下:


  1. // callback 
  2.     var resizeCB = function() { 
  3.         var hstyle = win.getComputedStyle(html, null), 
  4.             ffstr = hstyle['font-family'], 
  5.             pstr = "portrait, " + ffstr, 
  6.             lstr = "landscape, " + ffstr, 
  7.             // 拼接css 
  8.             cssstr = '@media (orientation: portrait) { .orientation{font-family:' + pstr + ';} } @media (orientation: landscape) {  .orientation{font-family:' + lstr + ';}}'; 
  9.         // 载入样式         
  10.         loadStyleString(cssstr); 
  11.         // 添加类 
  12.         html.className = 'orientation' + html.className; 
  13.         if (hstyle['font-family'] === pstr) { //初始化判断 
  14.             meta.init = 'portrait'; 
  15.             meta.current = 'portrait'; 
  16.         } else { 
  17.             meta.init = 'landscape'; 
  18.             meta.current = 'landscape'; 
  19.         } 
  20.         return function() { 
  21.             if (hstyle['font-family'] === pstr) { 
  22.                 if (meta.current !== 'portrait') { 
  23.                     meta.current = 'portrait'; 
  24.                     event.trigger('__orientationChange__', meta); 
  25.                 } 
  26.             } else { 
  27.                 if (meta.current !== 'landscape') { 
  28.                     meta.current = 'landscape'; 
  29.                     event.trigger('__orientationChange__', meta); 
  30.                 } 
  31.             } 
  32.         } 
  33.     }();  

完整代码猛击这里

测试效果

  • portrait效果:

  • landscape效果:

方案四:

可以再改进一下,在支持orientationchange时,就使用原生的orientationchange,不支持则使用方案三。

关键代码如下:


  1. // 是否支持orientationchange事件 
  2. var isOrientation = ('orientation' in window && 'onorientationchange' in window); 
  3. // callback 
  4. var orientationCB = function(e) { 
  5.     if (win.orientation === 180 || win.orientation === 0) { 
  6.         meta.init = 'portrait'; 
  7.         meta.current = 'portrait'; 
  8.     } 
  9.     if (win.orientation === 90 || win.orientation === -90) { 
  10.         meta.init = 'landscape'; 
  11.         meta.current = 'landscape'; 
  12.     } 
  13.     return function() { 
  14.         if (win.orientation === 180 || win.orientation === 0) { 
  15.             meta.current = 'portrait'; 
  16.         } 
  17.         if (win.orientation === 90 || win.orientation === -90) { 
  18.             meta.current = 'landscape'; 
  19.         } 
  20.         event.trigger(eventType, meta); 
  21.     } 
  22. }; 
  23. var callback = isOrientation ? orientationCB() : (function() { 
  24.     resizeCB(); 
  25.     return function() { 
  26.         timer && win.clearTimeout(timer); 
  27.         timer = win.setTimeout(resizeCB, 300); 
  28.     } 
  29. })(); 
  30. // 监听 
  31. win.addEventListener(isOrientation ? eventType : 'resize', callback, false);  

完整代码猛击这里

方案五:

目前,上述几种方案都是通过自定制的订阅与发布事件模式来实现的。这里可以基于浏览器的事件机制,来模拟orientationchange。即对orientationchange的不兼容进行修复。

关键代码如下:


  1. var eventType = 'orientationchange'; 
  2. // 触发原生orientationchange 
  3. var fire = function() { 
  4.     var e; 
  5.     if (document.createEvent) { 
  6.         e = document.createEvent('HTMLEvents'); 
  7.         e.initEvent(eventType, true, false); 
  8.         win.dispatchEvent(e); 
  9.     } else { 
  10.         e = document.createEventObject(); 
  11.         e.eventType = eventType; 
  12.         if (win[eventType]) { 
  13.             win[eventType](); 
  14.         } else if (win['on' + eventType]) { 
  15.             win['on' + eventType](); 
  16.         } else { 
  17.             win.fireEvent(eventType, e); 
  18.         } 
  19.     } 
  20. }  

作者:singsong

来源:51CTO

时间: 2024-08-31 19:29:30

更靠谱的移动端横竖屏检测方法的相关文章

更靠谱的H5横竖屏检测方法(js代码)_javascript技巧

前不久,做了一个H5项目,需要在横竖屏变化时,做一些处理.毫无疑问,需要使用orientationchange来监听横竖屏的变化. 方案一: // 监听 orientation changes window.addEventListener("orientationchange", function(event) { // 根据event.orientation|screen.orientation.angle等于0|180.90|-90度来判断横竖屏 }, false); 代码添加上

JS检测移动端横竖屏的代码_javascript技巧

使用media来判断屏幕宽度遇到的问题: ios上当我旋转屏幕的时候可行,但是安卓机上没反应,横屏显示的还是我竖屏的样式. 查了一下资料,css3的media如果要在移动端有较好的显示效果,需要在页头加上这段代码 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> 可是这段代码我不能用.因为我

Windows phone Store APP如何设置页面横竖屏

在 windows phone store app 中,判断和设置页面横竖屏的方法,与 silverlight 中的 Page 类 不同,不能直接通过 Page.Orientation 进行设置.而是通过 DisplayInformation 类,方法如下: // 横屏 Windows.Graphics.Display.DisplayInformation.AutoRotationPreferences = Windows.Graphics.Display.DisplayOrientations

解决Android横竖屏切换数据丢失问题的方法_Android

Android横竖屏切换时,当前的Activity会被销毁,然后Activity上面的数据将会全部丢失. 如Listview上面每个item的checkbox,横竖屏切换时,复选框就丢失所有选中信息. 解决方案1:在Androidmanifest.xml的activity标签中加入android:configChanges="orientation|keyboardHidden" <activity android:configChanges="orientation|

解决Android横竖屏切换数据丢失问题的方法

Android横竖屏切换时,当前的Activity会被销毁,然后Activity上面的数据将会全部丢失. 如Listview上面每个item的checkbox,横竖屏切换时,复选框就丢失所有选中信息. 解决方案1:在Androidmanifest.xml的activity标签中加入android:configChanges="orientation|keyboardHidden" <activity android:configChanges="orientation|

横竖屏切换-android app启动时根据是手机端还是Pad端进行横竖屏判断,以及不同布局

问题描述 android app启动时根据是手机端还是Pad端进行横竖屏判断,以及不同布局 如何判断一个app,如果运行在平板上,就横屏展示,如果运行在手机上就竖屏展示.而且在这两个端不允许横竖屏切换.而且MainActivity得长的不一样.意思就是要有两套布局.需要建什么资源文件夹 解决方案 http://jingyan.baidu.com/article/455a9950aa8aaea16627788a.html

UCD思想:横竖屏切换的设计的浅谈

文章描述:横竖都要给力--浅谈移动客户端的横竖屏切换设计评论. 随着技术与用户体验的发展,移动客户端产品中越来越多的需要横竖屏切换的设计.横竖屏旋转切换的设计在理想的情况下保持不变就能满足用户的需求.但也有很多时候,横竖屏切换时用户操作行为和屏幕比例的改变决定了客户端产品在设计时必须做出适当的针对性变化,于是对于交互设计而言,变不变.怎么变就成了一个普遍存在的问题. 应用背景 先从横竖屏切换需要的产生的背景说开. 横竖屏切换策略最早应用于QWERTY侧滑全键盘按键设计的手机上(早期塞班S60与W

Android布局之横竖屏切换

在默认情况下当屏幕从竖评变到横屏时会触发 onConfigurationChanged 事 件 在默认情况下会重新加载画面并显示和横屏一样的画面,这样会有2个问题, * 布局问题,在竖屏 显示的布局 到横屏中由于宽和高发生了变化所有多少 都会影响到布局(除非你定制2套画面在然后加个判断在横屏时怎么显示,在竖 屏时怎么显示),当然最简单的办法就是在 项目的AndroidManifest.xml中找到 你所指定的activity 中加上 o 只竖屏显示的话(android:screenOrienta

横竖都要给力 谈移动客户端横竖屏切换设计

随着技术与用户体验的发展,移动客户端产品中越来越多的需要横竖屏切换的设计.横竖屏旋转切换的设计在理想的情况下保持不变就能满足用户的需求.但也有很多时候,横竖屏切换时用户操作行为和屏幕比例的改变决定了客户端产品在设计时必须做出适当的针对性变化,于是对于交互设计而言,变不变.怎么变就成了一个普遍存在的问题. 应用背景 先从横竖屏切换需要的产生的背景说开. 横竖屏切换策略最早应用于QWERTY侧滑全键盘按键设计的手机上(早期塞班S60与Windows Mobile等智能操作平台),用户在使用键盘输入时