Click to Scroll ! ( 클릭해서 이동 )

Evan Lee ㅣ 2023. 6. 29. 01:15

토이프로젝트로 MBTI 테스트만드는데 디자인이 이렇게 나왔다. 

 

 

1. Ref를 통한 ScrollIntoView 메소드 

바닐라 자바스크립트에서는 Document에서 직접 DOM를 뽑아서 저 메소드를 사용했었지만, React에서는 useRef를 통해서 저 메소드를 사용해서 ref.current.scrollIntoView() 를 통해서 우리가 원하는 동작을 취할 수 있다. 

 

https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView

 

Element: scrollIntoView() method - Web APIs | MDN

The Element interface's scrollIntoView() method scrolls the element's ancestor containers such that the element on which scrollIntoView() is called is visible to the user.

developer.mozilla.org

 

2.  scrollIntoView 파라미터  ( Optional )

1. alignToTop : boolean

  • 참(true)인 경우, 해당 요소의 상단이 스크롤 가능한 부모 요소의 가시 영역의 상단에 맞춰집니다.  기본 값으로 scrollIntoViewOptions: {block: "start", inline: "nearest"} 에 해당합니다.
  • 거짓(false)인 경우, 해당 요소의 하단이 스크롤 가능한 부모 요소의 가시 영역의 하단에 맞춰집니다.  scrollIntoViewOptions: {block: "end", inline: "nearest"}에 해당합니다.

 

2. scrollIntoViewOptions

 

  • behavior (옵션): 스크롤링이 즉시 발생하는지 또는 부드럽게 애니메이션화되는지 여부를 결정합니다. 이 옵션은 다음 값 중 하나를 가져야 하는 문자열입니다:

smooth: 부드럽게 애니메이션화되는 스크롤링

instant: 한 번에 즉시 스크롤링이 발생

auto: 스크롤 동작은 scroll-behavior의 계산된 값에 따라 결정됩니다.

 

 

  • block (옵션): 수직 정렬을 정의합니다. start, center, end 또는 nearest 중 하나입니다. 기본값은 start입니다.
  • inline (옵션): 수평 정렬을 정의합니다. start, center, end 또는 nearest 중 하나입니다. 기본값은 nearest입니다.

 

 

3. ref 동적 할당 

 

방법은 간단하다. 먼저 useRef를 배열로 뽑아주고 map을 뿌림과 동시에 ref에 index통해 하나씩 차곡차곡 넣어주면 된다. 

그리고 버튼을 클릭하면 moveToNextQuestion에 다음 인덱스를 전달시켜서 이동하는 것을 볼 수 있다. 

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
const Component = () => {
    const questionRef = useRef<(HTMLDivElement | null)[]>([]);
    const moveToNextQuestion = (index: number) => {
        questionRef.current[index]?.scrollIntoView({
              behavior: 'smooth',
              block: 'center',
        });
        setCurrentStep(index);
      };
 
   return (
    <>
      {mbtiTest.map((test, index) => (
          <Question
            ref={(element) => (questionRef.current[index] = element)}
          >
            <button onClick={() => moveToNextQuestion(index + 1)}>{test.name}</button>
          </Question>
        ))}
     <>
   )    
 
}
 
cs

 

 

 

 여기까지만해도 일단 구현은 된다. 하지만 뭔가 아쉬웠다. 애니메이션이 이동하기전에 내가 클릭한게 무엇인지 확인을 해야했고, 우리는 앱뷰를 생각하기 때문에 hover를통해서도 할 수 없는 노릇이였다. 그래서 focus에 애니메이션을 줘서 나름 구현을 해보았다. 

 

4. 애니메이션 추가 

일단 저 클릭하는 박스에 css를 추가해주었습니다. 

&:focus {
    animation: blink 1s 1;
  }

  @keyframes blink {
    0%,
    20%,
    60%,
    100% {
      border: 2px solid #5344aa;
    }

    10%,
    30% {
      border: 2px solid #d9d8dc;
    }
  }
`;

 

그리고 이번에 알았지만 onClick대신에 onAnimationEnd라는 이벤트가 있었다. 

 

<Question
  isActive={currentStep === index}
  ref={(element) => (questionRef.current[index] = element)}
  onAnimationEnd={() => moveToNextQuestion(index + 1)}
>
{contents}         
</Question>

이렇게 해주면 위에 박스를 클릭하면 focus 애니메이션이 실행되고 애니메이션이 끝나면 onAnimationEnd에 있는 콜백함수를 실행해줍니다. 

 

'Study > React' 카테고리의 다른 글

useEffect 와 useLayoutEffect의 차이 ?  (0) 2023.01.14
JS와 JSX 사이의 차이는 무엇일까여 ?  (0) 2023.01.13
setState의 비동기성을 들어보셨습니까 ?  (0) 2022.12.10
Axios  (0) 2022.09.18
React - 공식문서 읽어보기4  (0) 2022.07.17