Web/React

React | number count 기능 구현하기 , onScroll 스크롤에 따라 animation 실행

Jun_N 2020. 8. 3. 15:33

 

먼저 react-spring을 사용해서 숫자 Count 애니메이션을 구현할 것이다.

 

react-spring은 React에서 여러 애니메이션을 구현하기 위해 사용하는 애니메이션이며 이를 사용하기 위해서는 npm을 통해 설치해야 한다.

https://www.react-spring.io/

 

react-spring

Bring your components to life with simple spring animation primitives for React

www.react-spring.io

 

사용하는 방법은 간단하다.

import { Spring } from 'react-spring/renderprops';

<Spring
  from={{ number: 시작 숫자 }}
  to={{ number: 마지막 숫자 }}
>
  {props => <div>{props.number}</div>}
</Spring>

 

내가 사용한 코드는 다음과 같다. 0부터 43109까지 Count를 하는 화면을 만들고 싶었고 다음과 같이 구현하였다.

먼저 count.jsx라는 js파일에 react-spring/renderprops를 import하고 이벤트를 원하는 곳에 Spring을 사용했다.

<span className="count__number">
              <Spring
                from={{ number: 0 }}
                to={{ number: 43109 }}
                delay={200}
                config={config.slow}
              >
                {(springProps) => {
                  return Math.round(springProps.number);
                }}
              </Spring>
            </span>

해당 class에 css를 꾸민 결과는 다음과 같다. (Css는 생략..) 

0부터 43109까지 올라가는것을 확인할 수있음. 

from 부터 to까지 delay만큼 기다렸다가 시작된다. config에는 slow를 걸어서 천천히 올라가는 모습을 확인 가능하다.

 

하지만 웹이 시작하자마자 숫자 애니메이션이 시작되기 때문에 내가 숫자가 올라가는것을 볼 수 없다.

내가 스크롤을 내렸을 때 원하는 위치에서 숫자가 올라가는것을 보려면 어떻게 해야할까??

onScroll을 사용하여 scrollTop을 state에 만든다. 

handleScroll에서 srcElement.scrollingElement.scrollTop으로 스크롤 값을 알 수 있다.

constructor() {
    super();
    this.state = {
      scrollTop: 0,
    };
  }

  componentDidMount = () => {
    window.addEventListener("scroll", this.handleScroll);
  };
  componentWillUnmount = () => {
    window.removeEventListener("scroll", this.handleScroll);
  };
  
  handleScroll = (e) => {
    const scrollTop = ("scroll", e.srcElement.scrollingElement.scrollTop);
   
    this.setState({
      scrollTop,
    });
 };

scrollTop에는 스크롤된 값이 저장된다.

 

 

이제 내가 스크롤을 어느정도 내렸을때 Animation을 실행시킬 것인지 계산해야 한다.

querySelector로 그 전 section들의 height을 구해 더해주어 threshold값으로 저장해뒀다. 그 뒤 scrollTop이 threshold 지점까지 내려왔을때 startOnMount 값을 true로 바꿔준다.  

startOnMount는 처음에는 false이다가 추후 원하는 지점까지 스크롤이 내려오면 true로 state를 바꿔준다.

constructor() {
    super();
    this.state = {
      scrollTop: 0,
      startOnMount: false,
    };
  }

handleScroll = (e) => {
    const scrollTop = ("scroll", e.srcElement.scrollingElement.scrollTop);
    const HomeSection = document.querySelector(".section");
    const MenuSection = document.querySelector(".menu_article");
    const homeHeight = HomeSection.getBoundingClientRect().height;
    const menuHeight = MenuSection.getBoundingClientRect().height;
    const threshold = homeHeight + menuHeight - 300;

    this.setState({
      scrollTop,
    });
    // 스크롤이 원하는 지점까지 내려왔을때..!! 딱 count number가 보일때!! 해야 할일
    if (scrollTop > threshold) {
      this.setState({ startOnMount: true });
    }
  };

 

<span className="count__number" onScroll={this.handleScroll}>
                {" "}
                {this.state.startOnMount ? (
                  <Spring
                    from={{ number: 0 }}
                    to={{ number: 43109 }}
                    delay={300}
                    config={config.slow}
                  >
                    {(springProps) => {
                      return Math.round(springProps.number);
                    }}
                  </Spring>
                ) : (
                  "0"
                )}
 </span>

startOnMout가 true이면 위에 만들어둔 Spring animation을 실행하고 false이면 text 0만 만들어 둔다.