Random-WebToon

oweaj·2023년 8월 20일
0

토이프로젝트

목록 보기
1/3
post-thumbnail

Gsap 기초 강의를 듣고 배운 부분들을 만들어보면서 적용해보면 좋겠다는 생각이들었다. 마침 웹툰에 빠져있었고 매주 보던 웹툰만 보는데 조건에 맞춰 랜덤으로 웹툰을 돌려서 다른 웹툰도 알아가면 좋겠다는 생각이들어 간단하게 만들어보았다.

✅ 구성

랜덤 웹툰을 만들기전에 전체적인 구성을 아래와 같이 생각했다.

  • main 페이지 하나로 구성

  • 페이지 배경은 웹툰들이 움직이는 슬라이드 식

  • 웹툰 조건 모달창을 띄워 랜덤으로 실행 (모달창 말고 룰렛도 생각해보기)

웹툰 정보 가져오기

useFetch라는 hook을 만들어 매개변수로 들어온 type에 맞춰 Korea-webtoon-api를 통해 웹툰 정보를 가져온다.

const useFetch = () => {
  const [webtoonList, setWebtoonList] = useState<webtoonInfo[]>([]);
  const [status, setStatus] = useState(0);

  const webtoons = async (type: string) => {
    try {
      const url = `https://korea-webtoon-api.herokuapp.com?${type}`;
      const response = await axios.get(url);
      setStatus(response.status);
      setWebtoonList(response.data.webtoons);
    } catch (error) {
      console.log(error);
    }
  };

  return { webtoons, webtoonList, status };
};

페이지 배경

가져온 웹툰 정보를 한 페이지에 수를 90개로 지정했고 상 중 하 처럼 3개의 분류로 30개씩 나눠 계속 애니메이션이 되도록 지정했다.
(중간 웹툰 슬라이드 애니메이션은 반대 방향으로 지정)

useEffect(() => {
    webtoons("perPage=90");
}, []);

const webtoonFirst = webtoonList.slice(0, webtoonList.length / 3);
const webtoonSecond = webtoonList.slice(webtoonList.length / 3, (webtoonList.length / 3) * 2);
const webtoonThird = webtoonList.slice((webtoonList.length / 3) * 2);

gsap.defaults({ play: true });
gsap.fromTo(firstRef.current, { duration: 40, yoyo: true, repeat: -1, ease: "sine-in" }, { x: -1500, duration: 50, yoyo: true, repeat: -1, ease: "sine-inout" });
gsap.fromTo(secondRef.current, { duration: 50, yoyo: true, repeat: -1, ease: "sine-in" }, { x: 1500, duration: 40, yoyo: true, repeat: -1, ease: "sine-inout" });
gsap.fromTo(thirdRef.current, { duration: 50, yoyo: true, repeat: -1, ease: "sine-in" }, { x: -1500, duration: 50, yoyo: true, repeat: -1, ease: "sine-inout" });


웹툰 조건 선택 및 랜덤 실행

먼저 아래 처럼 조건 버튼에 들어가는 정보를 배열 객체로 나타내서 map을 활용해서 각각 버튼에 해당 정보들을 넣어줬다.

// 버튼 정보을 담은 배열 객체
const infoType = [
  { title: "TYPE", content: ["NAVER", "KAKAO"] },
  { title: "DAY", content: ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"] },
];

조건 선택 버튼을 클릭하면 생성한 state number 배열에 버튼 index가 담기게 되면서 클릭한 버튼 스타일이 변경되고 state string 배열에는 버튼 정보를 담고있는 infoType 배열 객체의 item들의 title이 들어가게 되므로 콘솔을 찍어보면 어떤 조건 버튼을 클릭했는지 확인할 수 있다.

// 조건 선택 버튼 함수
  const [selectedId, setSelectedId] = useState<number[]>([-1, -1]);
  const [selectedName, setSeletedName] = useState<string[]>(["", ""]);

  const handleRoleClick = (content: string, typeIndex: number, contentIndex: number) => {
    // 선택된 버튼 id 배열
    const newArrId = [...selectedId];
    newArrId[typeIndex] = contentIndex;
    setSelectedId(newArrId);
    // 선택된 버튼 name 배열
    const newNames = [...selectedName];
    newNames[typeIndex] = content;
    setSeletedName(newNames);
  };

  const handleRoleBtn = (typeIndex: number, contentIndex: number) => {
    return selectedId[typeIndex] === contentIndex ? "bg-orange-400 text-white" : "bg-gray-400";
  };

조건 버튼을 선택했다면 마지막으로 랜덤 버튼을 실행하는데 조건을 선택했던 버튼의 정보를 담는 state의 배열들의 정보와 해당 웹툰의 페이지를 랜덤하게 지정하기 위해 randomPage를 통해 나온 값을 만들어둔 useFetch hook 안에 webtoons라는 비동기 함수에 인자로 해당 url type을 지정해준다.

// 랜덤 버튼 실행
const randomPage = Math.round(Math.random() * 50) + 1;

// 추가 수정 완료 
const handleRandomClick = async () => {
    setLoading(true);
    await webtoons(`perPage=2&page=${randomPage}&service=${selectedName[0].toLowerCase()}&updateDay=${selectedName[1].toLowerCase()}`);
    setLoading(false);
};

❗️랜덤 페이지에 조건에 맞는 웹툰이 없는 경우 처리

페이지 번호를 랜덤으로 지정해서 해당 조건의 웹툰을 찾다보니 가끔씩 해당 랜덤 페이지에 선택한 조건의 웹툰이 없는 경우가 생겼다.


전체적인 구성

  • 추가 수정 및 보완 완료


🔎 전체 코드 확인하기

🖇️ Reference

profile
데굴데굴데굴데굴데굴

0개의 댓글