前不久做了一个H5项目,需要做一些横竖屏变化时的处理。毫无疑问,需要使用orientationchange来监听横竖屏的变化。方案一://监听orientationchangeswindow.addEventListener("orientationchange",function(event){//根据event.orientation|screen.orientation.angle等于0|180,90|-90度判断横竖屏},错误的);添加代码后,出现各种兼容性问题。这里的兼容性问题出现在两个地方:orientationchangeevent.orientation|screen.orientation.angle下面是orientationchange事件的兼容性:下面是screen.orientation的兼容性:解决方法二:上面的解决方法不行,所以我们得另辟蹊径。google了一下,得知可以通过resize(window.inner/outerWidth,window.inner/outerHeight)实现:?"landscape":"portrait";if(oritentation==='portrait'){//dosomething……}else{//dosomethingelse……}},false);这种方案基本上可以满足大部分项目的需求,但是还是有一些不足:只要窗口大小发生变化,就会不断触发resize事件。您可以使用setTimeout对其进行优化。如果需要在多个地方监听横竖屏,需要注册多个window.addEventListener("resize",function(event){...})。是否可以通过订阅和发布的方式进行改进,只注册一个resize负责监听横竖屏的变化,只要发生横竖屏的变化,就会对订阅的对象发布通知。其他需要横竖屏监控的地方只需要订阅即可。关键代码如下:varresizeCB=function(){if(win.innerWidth>win.innerHeight){//初始化判断meta.init='landscape';meta.current='landscape';}else{meta.init='肖像';meta.current='肖像';}returnfunction(){if(win.innerWidth>win.innerHeight){if(meta.current!=='风景'){meta.current='风景';event.trigger('__orientationChange__',meta);}}else{if(meta.current!=='portrait'){meta.current='portrait';event.trigger('__orientationChange__',meta);}}}}();点击此处查看完整代码。方案三:不过,个人感觉window.innerWidth>window.innerHeight的实现是一种误检,有点不靠谱。可以通过浏览器实现检测吗?比如可以基于CSS3@media媒体查询来实现。@media兼容性如下:如上图所示,所有手机浏览器都支持CSS3媒体。实现思路:创建一个包含横竖屏状态的具体css样式。通过JS向页面注入CSS代码。在resize回调函数中获取横竖屏状态。这里我选择了的节点font-family作为检测样式属性。原因如下:选择主要是为了避免reflow和repaint。选择font-family风格,主要是因为font-family有以下特点:1.优先使用前面的字体。2.如果找不到字体,或者字体不包含要渲染的文本,则使用下一种字体。3.如果列出的字体都不能满足您的需要,让操作系统决定使用哪种字体。这样我们就可以指定一个具体的logo来标识横竖屏的状态,但是指定的logo需要放在其他字体的前面,这样hmtl字体就不会改变了。关键代码如下://callbackvarresizeCB=function(){varhstyle=win.getComputedStyle(html,null),ffstr=hstyle['font-family'],pstr="portrait,"+ffstr,lstr="landscape,"+ffstr,//拼接lstr+';}}';//加载样式loadStyleString(cssstr);//添加类html.className='orientation'+html.className;if(hstyle['font-family']===pstr){//初始化判断meta.init='portrait';meta.current='portrait';}else{meta.init='landscape';meta.current='landscape';}returnfunction(){if(hstyle['font-family']===pstr){if(meta.current!=='portrait'){meta.current='portrait';event.trigger('__orientationChange__',meta);}}else{if(meta.current!=='landscape'){meta.current='landscape';event.trigger('__orientationChange__',meta);}}}}();完整代码点这里测试效果人像效果:风景效果:方案四:可以改进暂时支持orientationchange时,使用原生orientationchange,不支持则使用方案三。关键代码如下://是否支持orientationchange事件varisOrientation=('orientation'inwindow&&'onorientationchange'inwindow);//callbackvarorientationCB=function(e){if(win.orientation===180||win.orientation===0){meta.init='肖像';meta.current='肖像';}if(win.orientation===90||win.orientation===-90){meta.init='风景';元。current='landscape';}returnfunction(){if(win.orientation===180||win.orientation===0){meta.current='portrait';}if(win.orientation===90||win.orientation===-90){meta.current='landscape';}event.trigger(eventType,meta);}};varcallback=isOrientation?orientationCB():(function(){resizeCB();returnfunction(){timer&&win.clearTimeout(timer);timer=win.setTimeout(resizeCB,300);}})();//监听win.addEventListener(isOrientation?eventType:'resize',callback,false);完成代码猛解决方案五点这里:目前,上述解决方案都是通过自定义订阅和发布事件的方式来实现的。这里可以根据浏览器的事件机制来模拟orientationchange。即修复orientationchange不兼容的问题。关键代码如下:vareventType='orientationchange';//触发原生orientationchangevarfire=function(){vare;if(document.createEvent){e=document.createEvent('HTMLEvents');e.initEvent(eventType,true,false);win.dispatchEvent(e);}else{e=document.createEventObject();e.eventType=eventType;if(win[eventType]){win[eventType]();}elseif(win['on'+eventType]){win['on'+eventType]();}else{win.fireEvent(eventType,e);}}}完整代码点这里通过以上5种方案,我改进了水平检测以及移动端竖屏的进一步理解,有些东西只有亲身体验过才能知道为什么会这样写,我也把原因记录在了文章中,希望对大家有所帮助。经过5种方案的演化,得到了最终的orientationchange-fix,github地址:https://github.com/zhansingsong/orientationchange-fix
