Kullanıcının HTML sayfasını görüp göremeyeceğini belirlemek için kullanılan 3 tipik yöntem vardır, ancak bunların hiçbiri mükemmel bir şekilde çalışmaz:
W3C Sayfa Görünürlük API'sı bunu gerekiyordu (: Firefox 10, MSIE 10, Chrome 13 beri desteklenir). Ancak, bu API yalnızca tarayıcı sekmesi tamamen geçersiz kılındığında (ör. Kullanıcı bir sekmeden diğerine değiştiğinde) olayları artırır. Görünürlük% 100 doğrulukla belirlenemediğinde API olayları artırmaz (örneğin, başka bir uygulamaya geçmek için Alt + Tab).
Odak / bulanıklaştırma tabanlı yöntemleri kullanmak size çok sayıda yanlış pozitif verir. Örneğin, kullanıcı tarayıcı penceresinin üstünde daha küçük bir pencere görüntülerse, tarayıcı penceresi odağı kaybeder ( onblur
yükseltilir), ancak kullanıcı yine de görebilir (bu yüzden yine de yenilenmesi gerekir). Ayrıca bkz. Http://javascript.info/tutorial/focus
- Kullanıcı etkinliğine (fare hareketi, tıklamalar, yazılan tuş) güvenmek size çok fazla yanlış pozitif verir. Yukarıdaki durumu veya video izleyen bir kullanıcıyı düşünün.
Yukarıda açıklanan kusurlu davranışları iyileştirmek için, 3 yöntemin bir kombinasyonunu kullanıyorum: W3C Görünürlük API'sı, daha sonra yanlış pozitif oranı azaltmak için odaklama / bulanıklık ve kullanıcı etkinliği yöntemleri. Bu, aşağıdaki olayları yönetmenizi sağlar:
- Tarayıcı sekmesini diğerine değiştirme (W3C Sayfa Görünürlüğü API'sı sayesinde% 100 doğruluk)
- Sayfa potansiyel olarak başka bir pencere tarafından gizlenmiş, örneğin Alt + Tab nedeniyle (olasılıklı =% 100 doğru değil)
- Kullanıcının ilgisi potansiyel olarak HTML sayfasına odaklanmadı (olasılıklı =% 100 doğru değil)
Bu şekilde çalışır: belge odağı kaybettiğinde, pencerenin görünür olup olmadığını belirlemek için belge üzerindeki kullanıcı etkinliği (fare hareketi gibi) izlenir. Sayfa görünürlüğü olasılığı, sayfadaki son kullanıcı etkinliğinin süresi ile ters orantılıdır: kullanıcı belgede uzun süre etkinlik yapmazsa, sayfa büyük olasılıkla görünmez. Aşağıdaki kod W3C Sayfa Görünürlüğü API'sını taklit eder: aynı şekilde davranır, ancak yanlış pozitif oranı küçüktür. Birden çok kasalı olma avantajına sahiptir (Firefox 5, Firefox 10, MSIE 9, MSIE 7, Safari 5, Chrome 9 üzerinde test edilmiştir).
<div id = "x"> </div>
<Script>
/ **
İşleyiciyi verilen nesnenin olaya kaydeder.
@param olayı artıracak nesneye itiraz et
Etkinlik türünü yazın: tıklayın, tuşa basın, fareyle üzerine gelme, ...
@param fn olay işleyici işlevi
@param isCapturing olay modunu ayarlar (true = yakalama olayı, false = köpürme olayı)
olay giderici doğru şekilde takılmışsa @return true
* /
function addEvent (obj, evType, fn, isCapturing) {
if (isCapturing == null) isCapturing = false;
if (obj.addEventListener) {
// Firefox
obj.addEventListener (evType, fn, isCapturing);
geri dönüş;
} else if (obj.attachEvent) {
// MSIE
var r = obj.attachEvent ('on' + evType, fn);
dönüş r;
} Başka {
yanlış döndür;
}
}
// potansiyel sayfa görünürlüğü değişikliğine kaydolun
addEvent (belge, "potansiyel görünürlük değişimi", işlev (olay) {
document.getElementById ("x"). innerHTML + = "potansiyelVisilityChange: potansiyelHidden =" + document.potentialHidden + ", document.potentiallyHiddenSince =" + document.potentiallyHiddenSince + "s <br>";
});
// W3C Sayfa Görünürlük API'sına kaydolun
var gizli = boş;
var visibilityChange = null;
if (typeof document.mozHidden! == "tanımsız") {
"MozHidden" = gizli;
visibilityChange = "mozvisibilitychange";
} else if (typeof document.msHidden! == "tanımsız") {
"MsHidden" = gizli;
visibilityChange "msvisibilitychange" =;
} else if (typeof document.webkitHidden! == "tanımsız") {
= "WebkitHidden" gizli;
visibilityChange "webkitvisibilitychange" =;
} else if (typeof document.hidden! == "gizli") {
= "Gizli" gizli;
visibilityChange = "visibilitychange";
}
if (hidden! = null && visibilityChange! = null) {
addEvent (belge, visibilityChange, function (event) {
document.getElementById ("x"). innerHTML + = visibilityChange + ":" + gizli + "=" + belge [gizli] + "<br>";
});
}
var potansiyelPageVisibility = {
pageVisibilityChangeThreshold: 3 * 3600, // saniye olarak
init: function () {
işlev kümesiAsNotHidden () {
var dispatchEventRequired = document.potentialHidden;
document.potentialHidden yanlış =;
document.potentiallyHiddenSince = 0;
if (dispatchEventRequired) dispatchPageVisibilityChangeEvent ();
}
function initPotentiallyHiddenDetection () {
if (! hasFocusLocal) {
// pencerenin odağı yok => pencerede kullanıcı etkinliğini kontrol et
lastActionDate = yeni Tarih ();
if (timeoutHandler! = null) {
clearTimeout (timeoutHandler);
}
timeoutHandler = setTimeout (checkPageVisibility, potansiyelPageVisibility.pageVisibilityChangeThreshold * 1000 + 100); // Firefox altında yuvarlama sorunlarını önlemek için +100 ms
}
}
function dispatchPageVisibilityChangeEvent () {
unifiedVisilityChangeEventDispatchAllowed yanlış =;
var evt = document.createEvent ("Olay");
evt.initEvent ("potansiyel görünürlük değişimi", doğru, doğru);
document.dispatchEvent (EVT);
}
function checkPageVisibility () {
var potansiyelHiddenDuration = (hasFocusLocal || lastActionDate == null? 0: Math.floor ((yeni Tarih (). getTime () - lastActionDate.getTime ()) / 1000));
document.potentiallyHiddenSince = potentialHiddenDuration;
if (potansiyelHiddenDuration> = potansiyelSayfaVisibility.pageVisibilityChangeThreshold &&! document.potentialHidden) {
// sayfa görünürlüğü değişiklik eşiği raiched => çift yükselt
document.potentialHidden doğru =;
dispatchPageVisibilityChangeEvent ();
}
}
var lastActionDate = null;
var hasFocusLocal = true;
var hasMouseOver = true;
document.potentialHidden yanlış =;
document.potentiallyHiddenSince = 0;
var timeoutHandler = null;
addEvent (belge, "sayfa gösterisi", işlev (etkinlik) {
document.getElementById ( "x") innerHTML + = "pageshow / doc: Ürün".;
});
addEvent (belge, "sayfa gizleme", işlev (olay) {
document.getElementById ( "x") innerHTML + = "pagehide / doc: Ürün".;
});
addEvent (pencere, "sayfa gösterisi", işlev (olay) {
document.getElementById ( "x") innerHTML + = "pageshow / kazan: <br>".; // sayfa ilk gösterildiğinde kaldırıldı
});
addEvent (pencere, "sayfa gizleme", işlev (olay) {
document.getElementById ( "x") innerHTML + = "pagehide / kazan: <br>".; // yükseltilmedi
});
addEvent (belge, "fare kaldırma", işlev (olay) {
lastActionDate = yeni Tarih ();
});
addEvent (belge, "fareyle üzerine gelme", işlev (olay) {
hasMouseOver doğru =;
) (SetAsNotHidden;
});
addEvent (belge, "fare kapanı", işlev (olay) {
hasMouseOver yanlış =;
initPotentiallyHiddenDetection ();
});
addEvent (pencere, "bulanıklaştırma", işlev (olay) {
hasFocusLocal yanlış =;
initPotentiallyHiddenDetection ();
});
addEvent (pencere, "odak", işlev (olay) {
hasFocusLocal doğru =;
) (SetAsNotHidden;
});
) (SetAsNotHidden;
}
}
potentialPageVisibility.pageVisibilityChangeThreshold = 4; // test için 4 saniye
potentialPageVisibility.init ();
</ Script>
Şu anda yanlış pozitif olmadan çalışan bir çapraz tarayıcı çözümü olmadığından, web sitenizdeki periyodik etkinliği devre dışı bırakmayı daha iyi düşünmelisiniz.
requestAnimationFrame
API'ya bakın veya pencere görünmediğindesetTimeout
/ sıklığınınsetInterval
azaltıldığı modern özelliği kullanın (örneğin, Chrome'da 1 sn).