更靠谱的横竖屏检测方法

参考链接:http://www.cnblogs.com/zhansingsong/p/5866692.html

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

方案一:

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

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

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

如下是orientationchange事件的兼容性:

如下是screen.orientation的兼容性:

 方案二:

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

window.addEventListener("resize", function(event) {
var orientation=(window.innerWidth > window.innerHeight)? "landscape":"portrait";
if(oritentation === ‘portrait‘){
// do something ……
} else {
// do something else ……
}
}, false);

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

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

关键代码如下:

    var resizeCB = function(){
      if(win.innerWidth > win.innerHeight){//初始化判断
        meta.init = ‘landscape‘;
        meta.current = ‘landscape‘;
      } else {
        meta.init = ‘portrait‘;
        meta.current = ‘portrait‘;
      }
      return function(){
        if(win.innerWidth > win.innerHeight){
          if(meta.current !== ‘landscape‘){
            meta.current = ‘landscape‘;
            event.trigger(‘__orientationChange__‘, meta);
          }
        } else {
          if(meta.current !== ‘portrait‘){
            meta.current = ‘portrait‘;
            event.trigger(‘__orientationChange__‘, meta);
          }
        }
      }
    }();

完整代码猛击这里

 方案三:

不过个人觉得通过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有如下特性:
  • 优先使用排在前面的字体。
  • 如果找不到该种字体,或者该种字体不包括所要渲染的文字,则使用下一种字体。
  • 如果所列出的字体,都无法满足需要,则让操作系统自行决定使用哪种字体。

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

关键代码如下:

    // callback
    var resizeCB = function() {
        var hstyle = win.getComputedStyle(html, null),
            ffstr = hstyle[‘font-family‘],
            pstr = "portrait, " + ffstr,
            lstr = "landscape, " + ffstr,
            // 拼接css
            cssstr = ‘@media (orientation: portrait) { .orientation{font-family:‘ + pstr + ‘;} } @media (orientation: landscape) {  .orientation{font-family:‘ + 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‘;
        }
        return function() {
            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);
                }
            }
        }
    }();

完整代码猛击这里

测试效果

  •  portrait效果:

  • landscape效果:

方案四:

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

关键代码如下:

// 是否支持orientationchange事件
var isOrientation = (‘orientation‘ in window && ‘onorientationchange‘ in window);
// callback
var orientationCB = function(e) {
    if (win.orientation === 180 || win.orientation === 0) {
        meta.init = ‘portrait‘;
        meta.current = ‘portrait‘;
    }
    if (win.orientation === 90 || win.orientation === -90) {
        meta.init = ‘landscape‘;
        meta.current = ‘landscape‘;
    }
    return function() {
        if (win.orientation === 180 || win.orientation === 0) {
            meta.current = ‘portrait‘;
        }
        if (win.orientation === 90 || win.orientation === -90) {
            meta.current = ‘landscape‘;
        }
        event.trigger(eventType, meta);
    }
};
var callback = isOrientation ? orientationCB() : (function() {
    resizeCB();
    return function() {
        timer && win.clearTimeout(timer);
        timer = win.setTimeout(resizeCB, 300);
    }
})();
// 监听
win.addEventListener(isOrientation ? eventType : ‘resize‘, callback, false);

完整代码猛击这里

方案五:

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

关键代码如下:

var eventType = ‘orientationchange‘;
// 触发原生orientationchange
var fire = function() {
    var e;
    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]();
        } else if (win[‘on‘ + eventType]) {
            win[‘on‘ + eventType]();
        } else {
            win.fireEvent(eventType, e);
        }
    }
}

完整代码猛击这里

通过上述5种方案,自己对移动端横竖屏检测有了更进一步的认识,有些东西只有自己亲身经历过才知道为什么要这么写,自己也把其中缘由记录在文章中,希望对大家有帮助。经过5种方案的演变得到了最终orientationchange-fix,github地址:https://github.com/zhansingsong/orientationchange-fix

时间: 2024-12-20 19:18:49

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

WP Store APP 设置页面横竖屏的方法

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

Android 横竖屏检测

package com.example; import android.app.Activity; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Bu

android 判断横竖屏的方法(转)

public boolean isScreenChange() { Configuration mConfiguration = this.getResources().getConfiguration(); //获取设置的配置信息 int ori = mConfiguration.orientation ; //获取屏幕方向 if(ori == mConfiguration.ORIENTATION_LANDSCAPE){ //横屏 return true; }else if(ori == mC

iOS 横竖屏切换(应对特殊需求)

iOS 中横竖屏切换的功能,在开发iOS app中总能遇到.以前看过几次,感觉简单,但是没有敲过代码实现,最近又碰到了,demo尝试了几种情况,这里就做下总结.注意 横屏两种情况是反的你知道吗? UIInterfaceOrientationLandscapeRight与UIInterfaceOrientationMaskLandscapeRight都代表横屏,Home键在右侧的情况:UIDeviceOrientationLandscapeLeft则是Home键在左侧. 一般情形 所有界面都支持横

强制设置页面横竖屏的问题

有的时候有的需求会让页面强制的横竖屏转换,再之后的ios的版本中,- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation被官方废弃了,不能继续使用的,下面是ios6之后的强制横竖屏的方法: -(BOOL)shouldAutorotate { return YES; } -(UIInterfaceOrientationMask)supportedInterfaceOrie

Android 切换横竖屏

一个项目一般会自己先定义项目是横屏还是竖屏但是也有可以横屏和竖屏之间切换的activty. 切换横竖屏的方法: //判断当前屏幕方向if(getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) { //切换竖屏 MainActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);}else{ //切换横屏 Ma

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

这篇文章主要介绍了JS检测移动端横竖屏的代码,需要的朋友可以参考一下 使用media来判断屏幕宽度遇到的问题: ios上当我旋转屏幕的时候可行,但是安卓机上没反应,横屏显示的还是我竖屏的样式. 查了一下资料,css3的media如果要在移动端有较好的显示效果,需要在页头加上这段代码 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-s

css3完美解决手机横竖屏判断,让用户看邀请函更爽

html: <div id="cover1"></div> <p id="cover1w">亲,请竖屏观看本屏内容,谢谢^_^</p> css: /* 判断手机横竖屏  */ @media screen and (orientation:portrait) { /*  css[竖向定义样式]  */ #cover1{display: none;width: 100%;height: 100%;background-co

检测手机横竖屏切换

我们做移动端项目的时候,为了更好的完善用户体会,经常会需要处理好手机横竖屏时候的效果,下面看一下通过代码如何判断手机是否是横竖屏,两种方式: 一.第一种方式: <style type="text/css">body,html { margin: 0; height: 100%; position: relative; overflow: hidden;} #box { width: 100%; height: 100%; font-size: 20px; position: