/* * https://github.com/morethanwords/tweb * Copyright (C) 2019-2021 Eduard Kuzmenko * https://github.com/morethanwords/tweb/blob/master/LICENSE */ type TargetType = HTMLElement; export type OnVisibilityChange = (target: TargetType, visible: boolean) => void; export default class VisibilityIntersector { private observer: IntersectionObserver; private items: Map = new Map(); private locked = false; constructor(onVisibilityChange: OnVisibilityChange) { this.observer = new IntersectionObserver((entries) => { if(this.locked) { return; } const changed: {target: TargetType, visible: boolean}[] = []; entries.forEach(entry => { const target = entry.target as TargetType; if(this.items.get(target) === entry.isIntersecting) { return; } else { this.items.set(target, entry.isIntersecting); } /* if(entry.isIntersecting) { console.log('ooo', entry); } */ /* if(this.locked) { return; } */ changed[entry.isIntersecting ? 'unshift' : 'push']({target, visible: entry.isIntersecting}); //onVisibilityChange(target, entry.isIntersecting); }); changed.forEach(smth => { onVisibilityChange(smth.target, smth.visible); }); }); } public getVisible() { const items: TargetType[] = []; this.items.forEach((value, key) => { if(value) { items.push(key); } }); return items; } public clearVisible() { const visible = this.getVisible(); for(const target of visible) { this.items.set(target, false); } } public isVisible(target: TargetType) { return this.items.get(target); } public disconnect() { this.observer.disconnect(); this.items.clear(); } public refresh() { this.observer.disconnect(); //window.requestAnimationFrame(() => { const targets = [...this.items.keys()]; for(const target of targets) { //this.items.set(target, false); this.observer.observe(target); } //}); } public refreshVisible() { const visible = this.getVisible(); for(const target of visible) { this.observer.unobserve(target); } for(const target of visible) { this.observer.observe(target); } } public observe(target: TargetType) { this.items.set(target, false); this.observer.observe(target); } public unobserve(target: TargetType) { this.observer.unobserve(target); this.items.delete(target); } public unlock() { this.locked = false; } public unlockAndRefresh() { this.unlock(); this.refresh(); } public lock() { this.locked = true; } }