티스토리 뷰

728x90
반응형

 

안녕하세요. Teus입니다.

 

이번에는 지금까지 만든 성분들이 한번에 Fade-in 되는것이 아니라

 

유저가 스크롤 함에 따라서 천천히 Fade-in 되는 효과를 만들어 보도록 하겠습니다.

 

# 1. Intersection Observer API

Intersect Observer API는 유저가 특정 Component에 관찰할 경우

 

해당 관찰 여부를 알려주는 Web표준 기능 입니다.

 

그래서 보통은 이 기술을 사용해서 인피니티스크롤(스크롤을 내리면 내리면서 계속 새로운 컨탠츠가 생기는 것)

 

을 구현할때 주로 사용됩니다.

 

이 Intersect Observer를 활용할 경우, 아래처럼 보다 미려한 모바일 청첩장을 만들수가 있죠

 

 

 

 

동영상으로 보니깐 뭔지 바로 이해게 되시죠?

 

# 2. 구현하기

지금까지는 모두 <div> tag 태에다가 각각의 Component를 집어넣었습니다.

 

이때 이 div tag를 대체할 Intersect Component를 만들도록 하겠습니다.

 

Intersect.jsx

import { useEffect, useRef, useState } from "react"
//parent로 받아온 props를 그대로 받아온다.
const Intersect = ({ children, ...props }) => {
    const ref = useRef()
    const [intersect, setIntersect] = useState(false)
    const observer = new IntersectionObserver(([entry]) => {
        //한번이라도 관찰이 되면, Observer가 더이상 관찰하지 않도록 한다.
        if (entry.isIntersecting){
            setIntersect(true)
            observer.disconnect()
        }        
    }, { threshold: 0.3})
    //Component가 mount되면서 동시에 Observer를 추가함
    useEffect(() => {
      observer.observe(ref.current)
      return () => observer.disconnect()
    }, [])
    return (
        <>
            {/* 관찰이 되면 props를 전달하고, 아니면 visibility를 hidden으로 한다. */}
            <div ref={ref} {...(intersect ? props : {style : {visibility: "hidden"}})}>
                {children}
            </div>
        </>
    )
}
export default Intersect
 

그리고 이렇게 만들어진 Intersect를 App.jsx에다가 적용시켜줍니다.

 

App.jsx

import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'


import { useEffect, useRef, useState } from 'react';
import Audiocomp from './Audiocomp'
import Topmsg from './Topmsg';
import Mainphoto from './Mainphoto';
import Invitation from './Invitation';
import Calendar from './Calendar';
import Gallery from './Gallery';
import Navi from './Navi';
import Account from './Account';
import Intersect from './Intersect';

function App() {
  const debug = process.env.NODE_ENV === 'development'?"solid":"none";
  return (
    <>
      <div className='main-frame'>
        <div style={{ border: debug, textAlign: 'right' }}>
          <Audiocomp/>
        </div>
        <Intersect className = "fade-in" style={{ border: debug}}>
          <Topmsg/>
        </Intersect>
        <Intersect className = "fade-in" style={{ border: debug}}>
          <Mainphoto/>
        </Intersect>
        <Intersect className = "fade-in" style={{ border: debug}}>
          <Invitation/>
        </Intersect>
        <Intersect className = "fade-in" style={{ border: debug}}>
          <Calendar/>
        </Intersect>
        <Intersect className = "fade-in" style={{ border: debug}}>
          <Gallery/>
        </Intersect>
        <Intersect className = "fade-in" style={{ border: debug}}>
          <Navi/>
        </Intersect>
        <Intersect className = "fade-in" style={{ border: debug}}>
          <Account/>
        </Intersect>
        <Intersect className = "fade-in" style={{ border: debug}}>
          카카오톡 공유하기 / 모청 주소 복사하기
        </Intersect>
      </div>
    </>
  )
}

export default App
 

이렇게 한 다음 App을 실행해보면

 

아래처럼 스크롤에 따라서 사용자가 가까워지면 부드럽게 해당하는 내용들이 보이는것을 확인할 수 있습니다.

 

 

 

 

728x90
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함