search_awesome/util/hook.ts

73 lines
2.0 KiB
TypeScript
Raw Normal View History

2022-11-29 01:52:44 +09:00
import {useEffect, useState} from 'preact/hooks';
import {JSX, RefObject} from 'preact';
export function useIntersectionObserver({
target,
onIntersect,
threshold = 0,
rootMargin = '0px',
enabled = true,
}:{
target: RefObject<Element>;
onIntersect: () => void;
threshold?: number;
rootMargin?: string;
enabled?: boolean;
}) {
useEffect(() => {
if (!enabled) {
return;
}
const observer = new IntersectionObserver(onIntersect, {
rootMargin,
threshold,
});
if (target.current) {
observer.observe(target.current);
}
return () => {
if (target.current) {
observer.unobserve(target.current);
}
};
}, [target.current, onIntersect, threshold, rootMargin, enabled]);
}
export function useRelativeTopOppacity({elem}:{elem: RefObject<Element>}) {
const [opacity, setOpacity] = useState(1);
useIntersectionObserver({
target: elem,
threshold: 0,
onIntersect: () => {
if (elem.current) {
addEventListener('scroll', updater);
}
}
});
return opacity;
function updater(){
if (elem.current) {
const el = elem.current;
const rect = el.getBoundingClientRect();
const upIntersect = Math.min(rect.bottom, el.clientHeight) / el.clientHeight;
const downIntersect = Math.min(window.innerHeight - rect.top, el.clientHeight) / el.clientHeight;
const intersect = Math.min(upIntersect, downIntersect);
if (intersect >= 0) {
let v = Math.min(Math.max(intersect, 0), 1);
v *= 4/3;
v = Math.min(Math.max(v, 0), 1);
setOpacity(v);
}
else{
setOpacity(1);
removeEventListener('scroll', updater);
}
}
}
}