perf: tiện ích render-gate (dừng vòng lặp vẽ khi ngoài màn hình/đổi tab)
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
// src/app/lib/render-gate.ts
|
||||
// Chỉ cho phép vòng lặp vẽ (rAF/setAnimationLoop) chạy khi phần tử nằm trong vùng nhìn
|
||||
// VÀ tab đang hiển thị. Gọi onChange(active) mỗi khi trạng thái đổi. Trả về hàm dọn dẹp.
|
||||
export function createRenderGate(
|
||||
element: Element,
|
||||
onChange: (active: boolean) => void,
|
||||
): () => void {
|
||||
let onScreen = false;
|
||||
let visible = typeof document === "undefined" ? true : !document.hidden;
|
||||
let last = false;
|
||||
|
||||
const emit = () => {
|
||||
const next = onScreen && visible;
|
||||
if (next !== last) {
|
||||
last = next;
|
||||
onChange(next);
|
||||
}
|
||||
};
|
||||
|
||||
const io = new IntersectionObserver(
|
||||
(entries) => {
|
||||
onScreen = entries.some((entry) => entry.isIntersecting);
|
||||
emit();
|
||||
},
|
||||
{ threshold: 0.01 },
|
||||
);
|
||||
io.observe(element);
|
||||
|
||||
const onVisibility = () => {
|
||||
visible = !document.hidden;
|
||||
emit();
|
||||
};
|
||||
document.addEventListener("visibilitychange", onVisibility);
|
||||
|
||||
return () => {
|
||||
io.disconnect();
|
||||
document.removeEventListener("visibilitychange", onVisibility);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user