react-scroll-load
Version:
A React Component to lazy load child Component relative to scrolled parent just as a wrapper
59 lines (58 loc) • 2.22 kB
JavaScript
import BaseOberver from './BaseObserver';
import execCallback from '../utils/execCallback';
import warn from '../utils/warn';
class VisibleObserver extends BaseOberver {
constructor(current, parent, setVisible, config) {
super(current, parent, setVisible, config);
this.observer = new IntersectionObserver((entries) => {
if (entries[0].intersectionRatio > this.getCurrentRatio()) {
setVisible(true);
execCallback(this.config.onLoad);
// 一旦可见就取消观测
this.cancelObservation();
}
}, {
root: parent,
rootMargin: this.getRootMargin(),
threshold: [this.getCurrentRatio()],
});
}
getCurrentRatio() {
const { offset } = this.config;
if (!offset) {
return 0;
}
const off = typeof offset === 'number' ? offset : offset[0];
if (off > 0) {
const placeholderHeight = this.current.clientHeight;
return Number((off / placeholderHeight).toFixed(2));
}
return 0;
}
getRootMargin() {
const { offset } = this.config;
if (!offset) {
return '0px';
}
const off = typeof offset === 'number' ? offset : offset[0];
if (off < 0) {
const offAbs = Math.abs(off);
const pHeight = this.current.clientHeight;
const pWidth = this.current.clientWidth;
warn('offset 设置应小于placeholder对应宽高的1/2', offAbs * 2 >= pHeight || offAbs * 2 >= pWidth);
const marginVertical = offAbs * 2 >= pHeight ? Math.floor(pHeight / 2) - 1 : offAbs;
const marginHorizontal = offAbs * 2 >= pWidth ? Math.floor(pWidth / 2) - 1 : offAbs;
return `${marginVertical}px ${marginHorizontal}px ${marginVertical}px ${marginHorizontal}px`;
}
return '0px';
}
observe() {
if (this.current) {
this.observer.observe(this.current);
}
}
cancelObservation() {
this.observer.disconnect();
}
}
export default VisibleObserver;