我有JavaScript,它周期性地执行活动。当用户没有在看站点时(例如,窗口或选项卡没有焦点),最好不要运行。

是否有一种方法可以使用JavaScript来做到这一点?

我的参考点:如果你正在使用的窗口不活跃,Gmail聊天就会播放声音。


当前回答

这对我很有效

document.addEventListener("visibilitychange", function() {
      document.title = document.hidden ? "I'm away" : "I'm here";
});

演示:https://iamsahilralkar.github.io/document-hidden-demo/

其他回答

这真的很棘手。考虑到以下要求,似乎没有解决方案。

该页包括您无法控制的iframe 您希望跟踪可见性状态更改,而不管更改是由选项卡更改(ctrl+ TAB)或窗口更改(alt+ TAB)触发的。

这是因为:

页面可视性API可以可靠地告诉您一个选项卡更改(即使使用iframes),但它不能告诉您用户何时更改了窗口。 监听窗口模糊/聚焦事件可以检测alt+选项卡和ctrl+选项卡,只要iframe没有焦点。

考虑到这些限制,可以实现一个组合的解决方案 -页面可见性API -窗口模糊/聚焦 ——document.activeElement

能够:

1)当父页有焦点时按ctrl+tab: YES 2) iframe有焦点时按ctrl+tab: YES 3)当父页有焦点时,alt+tab: YES 4)当iframe有focus时,alt+tab: NO <——bummer

当iframe有焦点时,你的模糊/焦点事件根本不会被调用,页面可视性API也不会在alt+选项卡上触发。

我以@AndyE的解决方案为基础,在这里实现了这个(几乎很好的)解决方案: https://dl.dropboxusercontent.com/u/2683925/estante-components/visibility_test1.html (对不起,我有一些麻烦与JSFiddle)。

这也可以在Github上找到:https://github.com/qmagico/estante-components

这适用于铬/铬。 它在firefox上工作,除了它不加载iframe内容(知道为什么吗?)

无论如何,为了解决最后一个问题(4),你能做的唯一方法是监听iframe上的模糊/聚焦事件。 如果你对iframe有一些控制,你可以使用postMessage API来做到这一点。

https://dl.dropboxusercontent.com/u/2683925/estante-components/visibility_test2.html

我还没有在足够多的浏览器上测试这个功能。 如果你能找到更多关于哪里不行的信息,请在下面的评论中告诉我。

var visibilityChange = (function (window) {
    var inView = false;
    return function (fn) {
        window.onfocus = window.onblur = window.onpageshow = window.onpagehide = function (e) {
            if ({focus:1, pageshow:1}[e.type]) {
                if (inView) return;
                fn("visible");
                inView = true;
            } else if (inView) {
                fn("hidden");
                inView = false;
            }
        };
    };
}(this));

visibilityChange(function (state) {
    console.log(state);
});

http://jsfiddle.net/ARTsinn/JTxQY/

这对我很有效

document.addEventListener("visibilitychange", function() {
      document.title = document.hidden ? "I'm away" : "I'm here";
});

演示:https://iamsahilralkar.github.io/document-hidden-demo/

简单的/立即检查:

if(document.hidden) {
  // do something
}

可见性变化事件:

document.addEventListener("visibilitychange", function() {
  console.log(document.visibilityState); // "hidden" or "visible"
}, false);

基于承诺的事件:

// An `await`able function that resolves when page visibility changes:
function visibilityChange(state="") {
  return new Promise(resolve => {
    document.addEventListener("visibilitychange", function() {
      if(!state || document.visibilityState === state) { 
        resolve(document.visibilityState);
        document.removeEventListener("visibilitychange", arguments.callee);
      }
    });
  });
}

// Use it like this:
await visibilityChange();
console.log(document.visibilityState);

// Or wait for page to become...
await visibilityChange("visible");
await visibilityChange("hidden");

(注:后两个解是我加到这个答案里的,因为这个问题现在已经结束了,我不能加我自己的答案。以防有人认为我抄袭了那篇文章而没有注明出处。)

U可以使用:

(function () {

    var requiredResolution = 10; // ms
    var checkInterval = 1000; // ms
    var tolerance = 20; // percent


    var counter = 0;
    var expected = checkInterval / requiredResolution;
    //console.log('expected:', expected);

    window.setInterval(function () {
        counter++;
    }, requiredResolution);

    window.setInterval(function () {
        var deviation = 100 * Math.abs(1 - counter / expected);
        // console.log('is:', counter, '(off by', deviation , '%)');
        if (deviation > tolerance) {
            console.warn('Timer resolution not sufficient!');
        }
        counter = 0;
    }, checkInterval);

})();