REACT

[React.js/TypeScript] Intersection Observer 구현해보기

user-anonymous 2022. 9. 20. 11:12
728x90

Intersection ObserverAPI를 사용하게 되면, 우린 특정 element가 viewport에 보일때 관찰이 가능하다. 주로 해당 기능을 페이지 성능 개선을 위해 Lazy Image loading에 사용하곤 한다. 

intersection observerAPi를 사용하지 않고, react.js, typescript를 사용하여 구현해보도록 하겠다. 

 

 

| 화면 크기 구하기

element가 viewport에 표시되는 것을 관찰하기 위해서는, window의 width, height를 먼저 알아내야한다. 

유동적 화면 변화를 위해선 eventHandler를 사용하여 크기를 감시해야한다. 

  useEffect(() => {
        handleObserveElement();
    }, [handleObserveElement]);

    useEffect(() => {
        window.addEventListener('resize', handleObserveElement);
        return () => {
            window.removeEventListener('resize', handleObserveElement);
        };
    }, [handleResize]);
 
    useEffect(() => {
        window.addEventListener('scroll', handleObserveElement);
        return () => {
            window.removeEventListener('scroll', handleObserveElement);
        };
    }, [handleObserveElement]);

리사이징 될 때마다 관찰함수를 실행시켜주도록 했다. 

 

 

| handleObserverElement 작성

   const [isViewing, setIsViewing] = useState<boolean>(false);

    const handleObserveElement = useCallback(() => {
        //viewport 크기 구하기
        let winH = window.innerHeight;
        let winW = window.innerWidth;

        let info1 = document.getElementById('box' + type)?.getBoundingClientRect();

        //y축 체크
        if (Number(info1?.y) < winH - 200 && Number(info1?.x) < winW) {
            setIsViewing(true);
        }
    }, [type]);
현재 element의 위치를 구하고 이의 y좌표가 윈도우의 높이에 들어올경우 화면에 보여진다고 지정하였다. 

임시로 200을 빼준 이유는 화면에 element가 보일 때를 눈으로 확인시켜주고 싶었다.

이렇게 isViewing이 true일 경우 div의 색상을 보여지도록 했다.

    return (
	<Box id={'box' + type} isView={isViewing}>
        {type}
    </Box>
)    
    
    const Box = styled.div<IBox>`
    background: pink;
    width: 200px;
    aspect-ratio: 1/1;

    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2rem;

    ${({ isView }) =>
        isView &&
        css`
            background-color: green;
            transition: 0.5s all ease-in;
        `}
`;
   

 

 

| 실행화면

 

 

| 사진 적용 

 

728x90
반응형