tweb/src/components/visibilityIntersector.ts
2021-08-03 04:44:13 +03:00

124 lines
2.8 KiB
TypeScript

/*
* 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<TargetType, boolean> = 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;
}
}