본문 바로가기
Coding/React

React - flicking

by z쿳쿳z 2021. 2. 21.
728x90
반응형

많은 웹사이트를 보면 배너가 있고 버튼을 누르거나, 배너 navigator(?) 같은거를 누르면 배너가 이동을 한다. React에서 이러한 기능을 해주는 라이브러리가 있다. flicking이라는 라이브러리다.

npm 사이트에서 flicking이라고 검색을 하면 flicking에 관련된 많은 라이브러리가 나온다. React를 사용했기 때문에 하기와 같은 라이브러리를 설치를 했다.

npm install --save @egjs/react-flicking

flicking에 대한 많은 property들은 공식 사이트에 나와있다. 설명이 잘되어 있다

@egjs/react-flicking : "^3.5.2"

naver.github.io/egjs-flicking/release/latest/doc/index.html

 

Index | egjs::Flicking - API

Everyday 30 million people experience. It's reliable, flexible and extendable carousel. 📱💻🖥 Translations: 🇺🇸 🇰🇷 Supported Frameworks       🖱️Click each images to see its source or check our full demos. Easy-to-use and performa

naver.github.io

 

flicking 라이브러를 활용해서 배너를 만들어 보았다. 

결론적으로 아래와 같은 배너를 만들었다.

배너 영상

 

 

기본적인 사진들은 unsplash에서 가져왔다.

밑에 네비게이터와 버튼을 통해서 이동하는 것을 코드로 구현을 했다.

 

기본적으로 라이브러리를 다운을 했으면 flicking라는 컴포넌트를 사용할 수 있다.

import Flicking from "@egjs/react-flicking";

그리고 property(속성값들을 넣어 줄수 있다.)

 

전체적인 코드를 보면(CSS는 material ui를 사용했다)

 

기본적으로 flicking component는 onChange 속성을 받을 수 있고, 기본적으로 event에서 index를 받을 수 있다. 이것을 활용해서 네이게이터를 구현을 했고, 방향버튼을 활용해서 flicking이 움직이도록 구현했다.

  *circle은 마지막 인덱스가 도달 했을떄, 처음으로 돌아갈지를 설정하는 property 이다.

  *duration은 애니메이션 이벤트가 발생했을때, 그 화면이 보이는 시간을 나타낸다. duration을 100으로 지정한 이유는 버튼을 클릭했을 때, 변화하는 인덱스값을 가장 잘 받아 들였다. duration이 200만 되더라고 버튼을 연속클릭했 때, 화면이 못 따라간다.

  *autoResize는 window에서 제공하는 resize 이벤트와 동일하다.

  

  *useEffect를 활용해서 flickingIndex값이 변화에 따라서 화면이 바뀌도록 설정을 했다. 그래서 변화가 있을 때마다 사진이 변화도록 설정해서 버튼을 클릭하거나 네비게이터의 원하는 index를 클릭하면 이동하도록 설정을 헸다.

 

처음에는 useEffect를 활용하지 않아서, 버튼을 클릭했을 떄, 한박자 느리게 반응을 했다. 이것 때문에 facebook 커뮤니티에 질문을 했었고, state 변경에 따라 re - render 되는 상황을 다시 공부하게 되었다.

 

지금은 네비게이터를 구현할 때, 임의로 지정한 배열이지만, 나중에는 서버에서 오는 배열로 바꿔서 거기에 맞게 mapping을 해주면 받아오는 데이터 만큼 네비게이터를 구현할 수 있을 것 같다.

 

  *버튼을 클릭했을 때, 인덱스 범위가 늘어나지 않도록 지정을 했다.

 

const FlickingComponent = () => {
  const classes = useStyles();

  const [flickingIndex, setFlcikingIndex] = useState({
    currentIndex: 0,
  });

  const flickingRef = useRef(null);

  const flickingOnChange = (e: any) => {
    setFlcikingIndex({ ...flickingIndex, currentIndex: e.index });
  };

  useEffect(() => {
    moveToFlicking(flickingIndex.currentIndex);
  }, [flickingIndex]);

  const moveToFlicking = (item: Number) => {
    const flicking: any = flickingRef.current;
    if (!flicking) {
      return;
    }
    flicking.moveTo(item);
  };

  const onClickArrowBackButton = () => {
    if (flickingIndex.currentIndex === 0) {
      setFlcikingIndex({
        ...flickingIndex,
        currentIndex: 2,
      });
    } else {
      setFlcikingIndex({
        ...flickingIndex,
        currentIndex: flickingIndex.currentIndex - 1,
      });
    }
  };

  const onClickArrowForwardButton = () => {
    if (flickingIndex.currentIndex === 2) {
      setFlcikingIndex({
        ...flickingIndex,
        currentIndex: 0,
      });
    } else {
      setFlcikingIndex({
        ...flickingIndex,
        currentIndex: flickingIndex.currentIndex + 1,
      });
    }
  };

  return (
    <Box className={classes.container}>
      <Box className={classes.flickingBox}>
        <Flicking
          className={classes.flicking}
          circular={true}
          duration={100}
          autoResize={true}
          onChange={flickingOnChange}
          ref={flickingRef}
        >
          <img
            className={classes.flickingImage}
            src={"images/giphy.gif"}
            alt={""}
          />
          <img
            className={classes.flickingImage}
            src={"images/unheart.png"}
            alt={""}
          />
          <img
            className={classes.flickingImage}
            src={"images/heart.png"}
            alt={""}
          />
        </Flicking>
        <Box className={classes.arrowButtonContainer}>
          <Button
            className={classes.arrowBackButton}
            onClick={onClickArrowBackButton}
          >
            <ArrowBackIosIcon />
          </Button>
          <Button
            className={classes.arrowForwardButton}
            onClick={onClickArrowForwardButton}
          >
            <ArrowForwardIosIcon />
          </Button>
        </Box>
      </Box>
      <Box className={classes.flickingNavContainerBox}>
        <Box className={classes.flickingNavBox} component={"ul"}>
          {[0, 1, 2].map(item => (
            <Box
              className={clsx(classes.flickingNavList, {
                [classes.selectedIndicator]:
                  flickingIndex.currentIndex === item,
              })}
              key={item}
              component={"li"}
              onClick={
                flickingIndex.currentIndex === item
                  ? undefined
                  : () => moveToFlicking(item)
              }
            ></Box>
          ))}
        </Box>
      </Box>
    </Box>
  );
};
728x90
반응형