มีวิธีการทั่วไป 3 วิธีที่ใช้ในการพิจารณาว่าผู้ใช้สามารถดูหน้า HTML ได้หรือไม่ แต่ไม่มีวิธีการใดที่สมบูรณ์แบบ:
W3C หน้า API การเปิดเผยควรจะทำเช่นนี้ (ได้รับการสนับสนุนตั้งแต่: Firefox 10 MSIE 10, Chrome 13) อย่างไรก็ตาม API นี้จะเพิ่มเหตุการณ์เฉพาะเมื่อแท็บเบราว์เซอร์นั้นเต็มไปหมด (เช่นเมื่อผู้ใช้เปลี่ยนจากแท็บหนึ่งเป็นอีกแท็บหนึ่ง) API จะไม่เพิ่มเหตุการณ์เมื่อไม่สามารถระบุการมองเห็นได้ด้วยความแม่นยำ 100% (เช่น Alt + Tab เพื่อเปลี่ยนเป็นแอปพลิเคชันอื่น)
การใช้วิธีการโฟกัส / เบลอจะให้ผลบวกที่ผิด ๆ มากมาย ตัวอย่างเช่นหากผู้ใช้แสดงหน้าต่างเล็ก ๆ ที่ด้านบนของหน้าต่างเบราว์เซอร์หน้าต่างเบราว์เซอร์จะสูญเสียการโฟกัส ( onblur
ยกระดับขึ้น) แต่ผู้ใช้ยังสามารถมองเห็นได้ (ดังนั้นจึงจำเป็นต้องรีเฟรช) ดูเพิ่มเติมที่http://javascript.info/tutorial/focus
- การใช้กิจกรรมของผู้ใช้ (การเลื่อนเมาส์คลิกการพิมพ์คีย์) จะให้ผลบวกที่ผิด ๆ มากมาย นึกถึงกรณีเดียวกับด้านบนหรือผู้ใช้ที่ดูวิดีโอ
เพื่อปรับปรุงพฤติกรรมที่ไม่สมบูรณ์ที่อธิบายไว้ข้างต้นฉันใช้การรวมกันของ 3 วิธี: W3C Visibility API จากนั้นทำการโฟกัส / เบลอและวิธีการใช้งานของผู้ใช้เพื่อลดอัตราบวกผิด ๆ สิ่งนี้อนุญาตให้จัดการเหตุการณ์ต่อไปนี้:
- การเปลี่ยนแท็บเบราว์เซอร์ไปเป็นอีกอันหนึ่ง (ความแม่นยำ 100% ขอบคุณ W3C Page Visibility API)
- หน้าอาจซ่อนโดยหน้าต่างอื่นเช่นเนื่องจาก Alt + Tab (probabilistic = ไม่ถูกต้อง 100%)
- ความสนใจของผู้ใช้อาจไม่ได้เน้นที่หน้า HTML (ความน่าจะเป็น = ไม่ถูกต้อง 100%)
นี่คือวิธีการทำงาน: เมื่อเอกสารสูญเสียการโฟกัสกิจกรรมของผู้ใช้ (เช่นการเลื่อนเมาส์) บนเอกสารจะถูกตรวจสอบเพื่อตรวจสอบว่าสามารถมองเห็นหน้าต่างได้หรือไม่ ความน่าจะเป็นในการเปิดเผยหน้านั้นจะแปรผกผันกับเวลาของกิจกรรมผู้ใช้ล่าสุดในหน้าเว็บ: หากผู้ใช้ไม่ได้ทำกิจกรรมบนเอกสารเป็นเวลานานหน้านั้นอาจไม่สามารถมองเห็นได้ โค้ดด้านล่างเลียนแบบ W3C Page Visibility API: มันทำงานในลักษณะเดียวกัน แต่มีอัตราบวกที่ผิดพลาดเล็กน้อย มันมีข้อดีที่จะเป็น multibrowser (ทดสอบบน Firefox 5, Firefox 10, MSIE 9, MSIE 7, Safari 5, Chrome 9)
<div id = "x"> </div>
<script>
/ **
ลงทะเบียนตัวจัดการเหตุการณ์สำหรับวัตถุที่กำหนด
@param obj วัตถุที่จะเพิ่มเหตุการณ์
@param evType ประเภทเหตุการณ์: คลิก, ปุ่มกด, เม้าส์, ...
@param fn ฟังก์ชันตัวจัดการเหตุการณ์
@param isCapturing ตั้งค่าโหมดเหตุการณ์ (true = เหตุการณ์การจับภาพ, false = เหตุการณ์เดือดปุด ๆ )
@return จริงหากตัวจัดการเหตุการณ์ได้รับการแนบอย่างถูกต้อง
* /
ฟังก์ชั่น addEvent (obj, evType, fn, isCapturing) {
if (isCapturing == null) isCapturing = false;
if (obj.addEventListener) {
// Firefox
obj.addEventListener (evType, fn, isCapturing);
กลับจริง
} อื่น ๆ ถ้า (obj.attachEvent) {
// MSIE
var r = obj.attachEvent ('บน' + evType, fn);
กลับ r;
} อื่น {
กลับเท็จ
}
}
// ลงทะเบียนเพื่อเปลี่ยนการเปิดเผยหน้าเว็บที่เป็นไปได้
addEvent (เอกสาร, "potentialvisilitychange", ฟังก์ชัน (เหตุการณ์) {
document.getElementById ("x"). InnerHTML + = "potentialVisilityChange: potentialHidden =" + document.potentialHidden + ", document.potentialHiddenSince =" + document.potentialHiddenSince + "s" ";
});
// ลงทะเบียนกับ W3C Page Visibility API
var hidden = null;
var visibleChange = null;
if (typeof document.mozHidden! == "undefined") {
ซ่อน = "mozHidden";
visibilityChange = "mozvisibilitychange";
} อื่นถ้า (typeof document.msHidden! == "undefined") {
ซ่อน = "msHidden";
visibilityChange = "msvisibilitychange";
} อื่นถ้า (typeof document.webkitHidden! == "ไม่ได้กำหนด") {
ซ่อน = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
} อื่นถ้า (typeof document.hidden! == "ซ่อน") {
ซ่อน = "ซ่อน";
visibilityChange = "visibilitychange";
}
if (hidden! = null && visibleChange! = null) {
addEvent (เอกสาร, ทัศนวิสัยเปลี่ยน, ฟังก์ชั่น (เหตุการณ์) {
document.getElementById ("x"). InnerHTML + = visibleChange + ":" + hidden + "=" + เอกสาร [ซ่อน] + "<br>";
});
}
var potentialPageVisibility = {
pageVisibilityChangeThreshold: 3 * 3600, // ในไม่กี่วินาที
init: function () {
ฟังก์ชัน setAsNotHidden () {
var dispatchEventRequired = document.potentialHidden;
document.potentialHidden = false;
document.potentiallyHiddenSince = 0;
ถ้า (dispatchEventRequired) dispatchPageVisibilityChangeEvent ();
}
ฟังก์ชัน initPotentiallyHiddenDetection () {
if (! hasFocusLocal) {
// หน้าต่างไม่มี focus => ตรวจสอบกิจกรรมของผู้ใช้ในหน้าต่าง
lastActionDate = new Date ();
if (timeoutHandler! = null) {
clearTimeout (timeoutHandler);
}
timeoutHandler = setTimeout (checkPageVisibility, potentialPageVisibility.pageVisibilityChangeThreshold * 1000 + 100); // +100 ms เพื่อหลีกเลี่ยงปัญหาการปัดเศษภายใต้ Firefox
}
}
ฟังก์ชั่น dispatchPageVisibilityChangeEvent () {
unifiedVisilityChangeEventDispatchAllowed = false;
var evt = document.createEvent ("เหตุการณ์");
evt.initEvent ("potentialvisilitychange", จริง, จริง);
document.dispatchEvent (EVT);
}
ฟังก์ชัน checkPageVisibility () {
var potentialHiddenDuration = (hasFocusLocal || lastActionDate == null? 0: Math.floor ((วันที่ใหม่ (). getTime () - lastActionDate.getTime ()) / 1000);
document.potentiallyHiddenSince = potentialHiddenDuration;
if (potentialHiddenDuration> = potentialPageVisibility.pageVisibilityChangeThreshold &&! document.potentialHidden) {
// หน้าเปลี่ยนเกณฑ์การมองเห็น raiched => ยกระดับ
document.potentialHidden = true;
dispatchPageVisibilityChangeEvent ();
}
}
var lastActionDate = null;
var hasFocusLocal = true;
var hasMouseOver = true;
document.potentialHidden = false;
document.potentiallyHiddenSince = 0;
var timeoutHandler = null;
addEvent (เอกสาร, "pageshow", ฟังก์ชัน (เหตุการณ์) {
document.getElementById ( "x") innerHTML + = "pageshow / doc: <br>".
});
addEvent (เอกสาร, "pagehide", ฟังก์ชัน (เหตุการณ์) {
document.getElementById ( "x") innerHTML + = "pagehide / doc: <br>".
});
addEvent (หน้าต่าง "pageshow", ฟังก์ชัน (เหตุการณ์) {
document.getElementById ( "x") innerHTML + = "pageshow / ชนะ: <br>". // เพิ่มเมื่อหน้าแรกแสดง
});
addEvent (หน้าต่าง "pagehide", ฟังก์ชัน (เหตุการณ์) {
document.getElementById ( "x") innerHTML + = "pagehide / ชนะ: <br>". // ไม่ยกขึ้น
});
addEvent (เอกสาร "mousemove", ฟังก์ชัน (เหตุการณ์) {
lastActionDate = new Date ();
});
addEvent (เอกสาร "mouseover", ฟังก์ชัน (เหตุการณ์) {
hasMouseOver = true;
setAsNotHidden ();
});
addEvent (เอกสาร "mouseout", function (event) {
hasMouseOver = false;
initPotentiallyHiddenDetection ();
});
addEvent (หน้าต่าง "เบลอ" ฟังก์ชั่น (เหตุการณ์) {
hasFocusLocal = false;
initPotentiallyHiddenDetection ();
});
addEvent (หน้าต่าง, "โฟกัส", ฟังก์ชัน (เหตุการณ์) {
hasFocusLocal = true;
setAsNotHidden ();
});
setAsNotHidden ();
}
}
potentialPageVisibility.pageVisibilityChangeThreshold = 4; // 4 วินาทีสำหรับการทดสอบ
potentialPageVisibility.init ();
</ script>
เนื่องจากขณะนี้ยังไม่มีโซลูชันข้ามเบราว์เซอร์ที่ใช้งานได้โดยไม่มีข้อผิดพลาดในเชิงบวกคุณควรคิดให้ดีขึ้นสองครั้งเกี่ยวกับการปิดใช้งานกิจกรรมเป็นระยะ ๆ บนเว็บไซต์ของคุณ
requestAnimationFrame
API หรือใช้คุณสมบัติที่ทันสมัยซึ่งความถี่ของsetTimeout
/setInterval
จะลดลงเมื่อมองไม่เห็นหน้าต่าง (เช่น 1 วินาทีใน Chrome เป็นต้น)