灏天阁

全屏和隐藏显示处理

· Yin灏

页面可见处理

HTML5 新增的 Page Visibility API 可以在浏览器窗口中设计只有当前激活的页面处于工作状态,其他隐藏页面将暂停工作,避免页面继续工作,耗费系统资源。

Page Visibility API 应用场景:

  1. 网站轮播图,只有在用户观看轮播的时候,才会自动展示下一显示信息。
  2. 仪表盘的应用程序不希望在页面不可见时轮询服务器进行更新。
  3. 页面想要检测是否正在渲染,以便可以准确计算网页浏览量。
  4. 当设备进入待机模式时,网站想要关闭设置声音(用户按下电源键关闭屏幕)。
  5. 可应用于视频站点,当用户进入页面播放,离开页面暂停。
  6. 可应用同登录同步。
  7. 可应用计算在线时长。
  8. 在线连天离线状态。

HTML5 之前,用户可以监听 focus 事件。如果当前窗口获得焦点,那么可以认为用户在与该页面交互,如果失去焦点,则可以认为用户停止了与该页面交互。

//当前窗口获得焦点
window.onfocus = function() {
    // 开始动画
    // 开始 Ajax 轮询
}
// 当前窗口失去焦点
window.onblur = function() {
    // 停止动画
    // 停止 Ajax 轮询
}

上面的方式略显简单,如果用户一边打开浏览器看视频,一边在另一个窗口工作,很显然,焦点集中在工作窗口,那么浏览器就失去了焦点,而无法正常浏览。Page Visibility API 能够有效帮助用户完全判断,避免不必要的尴尬。

Page Visibility API 是一个简单的 API,它包含两个属性和一个事件。

  • document.hidden 布尔值,表示页面是否隐藏。

页面隐藏包括:页面在后台标签页中,或者浏览器最小化。但是,页面被其他软件遮盖并不算隐藏。

  • document.visibilityState: 表示当前页面的可见性状态,包括 4 个可能状态值:

    • hidden: 页面在后台标签页中,或者浏览器最小化。
    • visible: 页面在前台标签中。
    • prerender: 页面在屏幕外执行预渲染处理,document.hidden 的为 true。
    • unloaded: 页面正在从内存中卸载。
  • visibilitychange 事件:当文档从可见变为不可见,或者从不可见变为可见时,将触发该事件。

通过监听 visibilitychange 事件,获取 document.hidden 的值,根据该值,对页面进行处理。

document.addEventListener('visibilitychange', function() {
  var isHidden = document.hidden;
  if(isHidden) {
    console.log('隐藏了');
  } else {
    console.log('显示了');
  }
})

使用 onfocus/onblur 事件可以兼容低版本 IE 浏览器。

(function() {
    var hidden = "hidden";
    //标准用法 
    if (hidden in document)
        document.addEventListener("visibilitychange", onchange);
    else if ((hidden = "mozHidden") in document)
        document.addEventListener("mozvisibilitychange", onchange);
    else if ((hidden = "webkitHidden") in document)
        document.addEventListener("webkitvisibilitychange", onchange);
    else if ((hidden = "msHidden") in document)
        document.addEventListener("msvisibilitychange", onchange);
    //兼容IE9-
    else if ("onfocusin" in document)
        document.onfocusin = document.onfocusout = onchange;
    //兼容其他浏览器
    else
        window.onpageshow = window.onpagehide = window.onfocus = window.onblur = onchange;
    function onchange (evt) {
        var v = "visible", h = "hidden",
                evtMap = {
                    focus:v, focusin:v, pageshow:v, blur:h, focusout:h, pagehide:h
                };
        evt = evt || window.event;
        if (evt.type in evtMap)
            document.body.className = evtMap[evt.type];
        else
            document.body.className = this[hidden] ? "hidden" : "visible";
    }
	//设置初始状态(仅当浏览器支持页面可见性API)
    if( document[hidden] !== undefined )
        onchange({type: document[hidden] ? "blur" : "focus"});
})();

案例:视频暂停与自动播放

<!DOCTYPE html>

<head>
    <meta charset="UTF-8">
    <title></title>
</head>

<body>
    <video id="videoElement" autoplay controls width="480" height="270">
        <source src="video/chrome.webm" type="video/webm" />
        <source src="video/chrome.ogv" type="video/ogg" />
        <source src="video/chrome.mp4" type="video/mp4; codecs='avc1.42E01E, mp4a.40.2'" />
    </video>
    <script>
        // 记录变量,监测视频是否暂停
        // 视频设置为自动播放,所以开始不停了
        sessionStorage.isPaused = "false";
        // 设置隐藏属性和可见性变化事件的名称
        var hidden, visibilityChange;
        if (typeof document.hidden !== "undefined") {
            hidden = "hidden";
            visibilityChange = "visibilitychange";
        } else if (typeof document.mozHidden !== "undefined") {
            hidden = "mozHidden";
            visibilityChange = "mozvisibilitychange";
        } else if (typeof document.msHidden !== "undefined") {
            hidden = "msHidden";
            visibilityChange = "msvisibilitychange";
        } else if (typeof document.webkitHidden !== "undefined") {
            hidden = "webkitHidden";
            visibilityChange = "webkitvisibilitychange";
        }
        var videoElement = document.getElementById("videoElement");
        // 如果该页面是隐藏的,则暂停视频
        // 如果显示页面,则播放视频
        function handleVisibilityChange() {
            if (document[hidden]) {
                videoElement.pause();
            } else if (sessionStorage.isPaused !== "true") {
                videoElement.play();
            }
        }
        //如果浏览器不支持addEventListener或者页面可见性API,则进行警告
        if (typeof document.addEventListener === "undefined" ||
            typeof hidden === "undefined") {
            alert("本例需要一个浏览器,如谷歌浏览器,支持页面可见性API。");
        } else {
            // 处理页面可见性变化
            document.addEventListener(visibilityChange, handleVisibilityChange, false);
            // 当视频停顿
            videoElement.addEventListener("pause", function() {
                if (!document[hidden]) {
                    // 如果现在不是因为页面隐藏而暂停,则设置ispaused为真
                    sessionStorage.isPaused = "true";
                }
            }, false);
            // 当视频播放,设置ispaused状态
            videoElement.addEventListener("play", function() {
                sessionStorage.isPaused = "false";
            }, false);
            // 以当前视频时间设置文档的标题
            videoElement.addEventListener("timeupdate", function() {
                document.title = Math.floor(videoElement.currentTime) + " second(s)";
            }, false);
        }
    </script>

</body>

</html>

全屏显示处理

Fullscreen API 基础

使用 HTML5 新增的 Fullscreen API,可以设计全屏显示模式应用。用户可以通过 DOM 对象的根节点(document.documentElement) 或某个元素的 requestFullscreen() 方法请求 Fullscreen API

下面函数 launchFullscreen() 可以根据传入的元素,让该元素全屏显示。

function launchFullscreen(element) {
  if(element.requestFullscreen) {
    element.requestFullscreen();
  } else if(element.mozRequestFullscreen) {
    element.mozRequestFullscreen();
  } else if(element.msRequestFullscreen) {
    element.msRequestFullscreen();
  } else if(element.webkitRequestFullscreen) {
    element.webkitRequestFullscreen();
  }
}

最新版本的浏览器都支持这个 API,但是在使用时需要加上前缀,使用的时候可以针对整个网页,也可以针对某个网页元素。

launchFullscreen(document.documentElement);
launchFullscreen(document.getElementId('videoElement'));

使用 exitFullscreen()CancelFullscreen() 方法可以取消全屏显示。

function exitFullscreen() {
  if(document.exitFullscreen) {
    document.exitFullscreen();
  } else if(document.msExitFullscreen) {
    document.msExitFullscreen();
  } else if(document.mozCancelFullscreen) {
    document.mozCancelFullscreen();
  } else if(document.webkitExitFullscreen) {
    document.webkitExitFullscreen();
  }
}
exitFullscreen();

Fullscreen API 还定义了两个属性:

  • document.fullscreenElement: 返回正处于全屏状态的网页元素。
  • document.fullscreenEnabled: 返回一个布尔值,表示当前是否处于全屏状态。

判断当前页面是否全屏显示,并获取当前全屏显示的元素。

var fullscreenEnabled = document.fullscreenEnabled || document.mozFullscreenEnabled || document.webkitFullscreenEnabled || document.msFullscreenEnabled;

var fullscreenElement = document.fullscreenElement || document.mozFullscreenElement || document.webkitFullscreenElement;

在全屏状态下,大多数浏览器的 css 支持 full-screen 伪类,而 IE11+ 支持 fullscreen 伪类,使用这个伪类,可以对全屏状态设置单独的 css 样式。

:-webkit-full-screen { /* 通用样式 */ }
:-moz-full-screen { /* 通用样式 */ }
:-ms-full-screen { /* 通用样式 */ }
:full-screen { 
  /* 特殊样式 */
  /* 通用样式 */
}
:fullscreen {
  /* 特殊样式 */
  /* 通用样式 */
}
:webkit-full-screen video { /* 更深层次的元素 */
    width: 100%;
    height: 100%;
}

当进入或退出全屏模式时,会触发 fullscreenchange 事件,利用该事件可以监测全屏状态的改变,以便及时作出各种页面响应。

在事件处理函数中,可以通过 DOM 对象的 fullscreen 属性值来判断页面或元素是否处于全屏显示状态。

document.addEventListener("fullscreenchange", function () {    
    fullscreenState.innerHTML =(document.fullscreen) ? "全屏显示" : "非全屏显示";
    btnFullScreen.value=(document.fullscreen) ? "页面非全屏显示": "页面全屏显示";
}, false);
document.addEventListener("mozfullscreenchange", function () {
    fullscreenState.innerHTML =(document.mozFullScreen) ? "全屏显示" : "非全屏显示";
    btnFullScreen.value=(document.mozFullScreen) ? "页面非全屏显示": "页面全屏显示";
}, false);
document.addEventListener("webkitfullscreenchange", function () {
    fullscreenState.innerHTML =(document.webkitIsFullScreen) ? "全屏显示" : "非全屏显示";
    btnFullScreen.value=(document.webkitIsFullScreen) ? "页面非全屏显示": "页面全屏显示";
}, false);

案例:全屏视频播放

设计当按 Enter 键时,视频会自动全屏播放,再次按 EnterESC 键,则退出全屏播放模式。

<!doctype html>
<html>

<head>
    <title></title>
    <style type="text/css">
        /* 使视频拉伸以填充在WebKit的屏幕 */
        
        :-webkit-full-screen #videoElement {
            width: 100%;
            height: 100%;
        }
    </style>
</head>

<body>
    <p>注意:按回车键切换全屏模式</p>
    <video id="videoElement" autoplay controls width="480" height="270">
    <source src="video/chrome.webm" type="video/webm" />
    <source src="video/chrome.ogv" type="video/ogg" />
    <source src="video/chrome.mp4" type="video/mp4; codecs='avc1.42E01E, mp4a.40.2'" />
</video>
</body>
<script>
    var videoElement = document.getElementById("videoElement");

    function toggleFullScreen() {
        if (!document.mozFullScreen && !document.webkitFullScreen) {
            if (videoElement.mozRequestFullScreen) {
                videoElement.mozRequestFullScreen();
            } else {
                videoElement.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
            }
        } else {
            if (document.mozCancelFullScreen) {
                document.mozCancelFullScreen();
            } else {
                document.webkitCancelFullScreen();
            }
        }
    }
    document.addEventListener("keydown", function(e) {
        if (e.keyCode == 13) {
            toggleFullScreen();
        }
    }, false);
</script>

</html>

- Book Lists -