zoukankan      html  css  js  c++  java
  • js倒计时 手机休眠时 时间不进行减少

    http://www.111cn.net/wy/js-ajax/94218.htm

    手机版网页js倒计时存在的问题与解决的方法

    www.111cn.net 更新:2015-09-16 编辑:kp12345 来源:转载
    js倒计时我们做过很多了但在使用过程中会有时差问题,特别是在手机中会发现js倒计时时间有问题了,下面来看如何处理这些问题。

    在手机版网页中做倒计时(使用服务端时间来倒计时)我们需要考虑到两个问题:1、避免频繁的取服务端时间,2、手机处于锁屏状态或者浏览器/页面在后台运行对倒计时的处理;围绕这两个问题说说我的解决方法(小 虾虎 鱼原创)。

    一、服务端时间的获取方法

    实现倒计时功能,我们必须要知道剩余时间,知道剩余时间就必须要知道当前时间(服务器时间)和结束时间。 服务器时间和结束时间可以通过两种方式获得:

    后端直接在视图中输出;

    通过ajax去获取;

    为了减少http请求我选择第一种方式,将结束时间和服务端时间直接在视图中输出,如:

    <head>
        <script>
            var servertime = '2015-4-10 09:32:17'; 
            var endtime = '2015-4-12 09:00:00';
        </script>
    </head>

    得到两个时间之后,结束时间endtime是一直不变的,但服务器时间servertime是一直在变的,而我们只得到了一次服务器时间,这时我们需要实现如何与服务器时间同步,我们可以这样做: 在页面打开时我同时记录这一刻的时间,并将这时间保存到一个变量instant中,然后在页面打开后的任一时间想得到服务端的时间可以通过当前本地的时间减去instant的时间再加上servertime时间,即:Date.now() - instant + servertime,我们将下面的js代码放到html页面中的head中(放到head中instant与servertime是同时定义可以减少误差):

    var servertime = '2015-4-10 09:32:17'; 
    var endtime = '2015-4-12 09:00:00';
    var instant = Date.now();

    最后我们通过Date.now() - instant + servertime计算时间差来实现倒计时。

    【注意】使用此方法会存在以下问题:

    如果客户端的时间被修改,那么得到的服务端时间就不正确;
    如果网络环境差也会造成一定的误差;

    二、设备锁屏或浏览器/页面后台运行的影响

    如果设备处于锁屏或者浏览器/页面处于后台运行状态过一段时间再返回到页面,会发现倒计时慢了(具体原因我不知道,有可能浏览器处于休眠状态导致JS的执行暂停,纯属猜测),这时我们需要对倒计时进行校正,对于这个问题我也有两种解决方法:

    使用定时器隔一段时间自动校正一次;
    使用visibilitychange事件来监听document的隐藏状态,即查看document.hidden值,false为页面显示,true为页面隐藏:

    document.addEventListener("visibilitychange", function (e) {
    
         if(!e.path[0].hidden){ // e.path为页面中document的集合
    
             // 校正倒计时的代码...
    
         } 
    
    }, false);

    第一种方法随可行但有一定的弊端,建议使用第二种方法。
    至此,手机版网页js倒计时的两个问题得到了解决。

    http://www.jianshu.com/p/ed46926a392c

    [JavaScript] visibilitychange事件

    visibilitychange事件是浏览器新添加的一个事件,
    当浏览器的某个标签页切换到后台,或从后台切换到前台时就会触发该消息,
    现在主流的浏览器都支持该消息了,例如Chrome, Firefox, IE10等。

    document.addEventListener("visibilitychange", function(){
        alert();
    }, false);

    现在某些浏览器还保留了visibilitychange的前缀,
    例如Chrome浏览器还保留着webkit前缀,
    不过该事件已经趋于稳定,在Chrome 33及以后就去掉了前缀,
    直接使用visibilitychange

    注:
    (1)微信内置的浏览器因为没有标签,所以不会触发该事件。
    (2)手机端直接按Home键回到桌面,也不会触发该事件。
    (3)PC端浏览器失去焦点不会触发该事件,但是最小化,或回到桌面会触发。

    http://www.51xuediannao.com/html5/visibilitychange.html 

    当前窗口获得焦点js事件【visibilitychange】

    当前窗口获得焦点js事件,html5发布之前我们使用window.onfocus和window.onblur来获得窗口焦点和失去窗口焦点,使用html5的Page Visibility API来实现

    当前窗口获得焦点js事件,html5发布之前我们使用window.onfocus和window.onblur来获得窗口焦点和失去窗口焦点,

     监听 onfocus() 和window.onblur()事件实现

    //当前窗口得到焦点 
    window.onfocus = function() { 
      //播放动画或视频 
    }; 
     
    //当前窗口失去焦点 
    window.onblur = function() { 
      //暂停动画或视频 
    };

    这个方法可以实现切换标签暂停动画视频,但是会带来一个问题,由于是判断焦点,如果是在当前页面上铺上一个小窗口,那当前页面就暂停了动画,试想,如果你一边看片,一边开个聊天窗口与MM聊天,当你操作聊天窗口的时候,视频暂停了,这并不是你想要的效果。

    现在我们来看看HTML5是怎么解决的。H5 提供了很多简单实用的 API,Page Visibility API 就是其中之一。 Page Visibility API能有效的帮助我们完成这样的判断。

     使用html5的Page Visibility API来实现

    这个 API 本身非常简单,由以下三部分组成。

    document.hidden:表示页面是否隐藏的布尔值。页面隐藏包括 页面在后台标签页中 或者 浏览器最小化 (注意,页面被其他软件遮盖并不算隐藏,比如打开的 sublime 遮住了浏览器)。

    document.visibilityState:表示下面 4 个可能状态的值

    hidden:页面在后台标签页中或者浏览器最小化

    visible:页面在前台标签页中

    prerender:页面在屏幕外执行预渲染处理 document.hidden 的值为 true

    unloaded:页面正在从内存中卸载

    Visibilitychange事件:当文档从可见变为不可见或者从不可见变为可见时,会触发该事件。

    这样,我们可以监听 Visibilitychange 事件,当该事件触发时,获取 document.hidden 的值,根据该值进行页面一些事件的处理。

    document.addEventListener('visibilitychange', function() { 
      var isHidden = document.hidden; 
      if (isHidden) { 
        // 动画视频暂停 
      } else { 
        // 动画视频开始 
      } 
    });

    结合demo中的实例,切换标签或者最小化的时候,demo中的视频会暂停,恢复当前页面时,demo中的视频会继续播放。完整的代码如下:

    var hidden, visibilityChange;  
    if (typeof document.hidden !== "undefined") {  
      hidden = "hidden"; 
      visibilityChange = "visibilitychange"; 
    } 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 { 
        videoElement.play(); 
      } 
    } 
     
    // 判断浏览器的支持情况 
    if (typeof document.addEventListener === "undefined" || typeof document[hidden] === "undefined") { 
      consol.log("This demo requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API."); 
    } else { 
      // 监听visibilityChange事件    
      document.addEventListener(visibilityChange, handleVisibilityChange, false); 
         
      // 当播放器暂停的时候,将页面标题设置为:Paused. 
      videoElement.addEventListener("pause", function(){ 
        document.title = 'Paused'; 
      }, false); 
         
      // 当播放器正常播放时,将页面标题设置为:Playing. 
      videoElement.addEventListener("play", function(){ 
        document.title = 'Playing';  
      }, false); 
    }
  • 相关阅读:
    Codeforces 992C(数学)
    Codeforces 990C (思维)
    Codeforces 989C (构造)
    POJ 1511 Invitation Cards(链式前向星,dij,反向建边)
    Codeforces 1335E2 Three Blocks Palindrome (hard version)(暴力)
    POJ 3273 Monthly Expense(二分)
    POJ 2566 Bound Found(尺取前缀和)
    POJ 1321 棋盘问题(dfs)
    HDU 1506 Largest Rectangle in a Histogram(单调栈)
    POJ 2823 Sliding Window(单调队列)
  • 原文地址:https://www.cnblogs.com/jcz1206/p/6900238.html
Copyright © 2011-2022 走看看