Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ 3주차 기본/심화 과제 ] 😎 진짜 궁금하다...당신.. #4

Closed
wants to merge 14 commits into from

Conversation

iamphj3
Copy link
Collaborator

@iamphj3 iamphj3 commented Nov 1, 2022

😎 진짜 궁금하다...당신..

✨ 구현 기능 명세

  • 기본 과제

    • 1. 이름을 올바르게 클릭한다면, 위 점수가 증가하고, 다음 사진으로 넘어갑니다

      정답을 맞추면 +1점, 틀리면 -1점이 되고 새로운 문제로 넘어갑니다.

      const onClickOption = (e) => {
              if (e.currentTarget.innerText === answer.person) {
                  // 정답 모달
                  setMessage("정답!!!!😆 +1점!!");
                  setIsOpen(true);
                  onClickAnswer();
                  setScore((prev) => prev + 1);
              } else {
                  // 오답 모달
                  setMessage("실망이야....-1점!!!😡");
                  setIsOpen(true);
                  setScore((prev) => prev - 1);
              }
              // 1) 선지 클릭 후 member 섞기(sort)
              // sort()는 음수, 양수, 0의 결과 값에 따라 정렬을 하는데, Math.random() - 0.5는 무작위로 음수, 양수, 0을 리턴하기 때문에 배열이 무작위로 정렬된다. (Math.random()는 0이상 1미만의 숫자를 리턴함)
              setMembers((prev) => [...prev].sort(() => Math.random() - 0.5));
          };
      
    • 2. 다시보기 버튼을 클릭한다면, 사진은 첫 번째 사진으로 돌아오고 점수는 0점이 됩니다

      다시보기 버튼 클릭 시 새로고침되며 점수가 초기화됩니다.

      const onClickRestart = () => {
          window.location.reload();
      };
      
    • 3. 전부 맞추게 된다면 (예시에서는 5개), 완료했다는 UI 를 보여줍니다

      점수가 5점 이상이면 성공, 0점 미만이면 실패했다는 텍스트와 이미지를 보여주었습니다.

              {score >= 5 ? (
                  <Ending>
                      <img src="../assets/win.gif" alt="game over" />
                      😇😇😇 YOU WIN !!! 😇😇😇
                  </Ending>
              ) : score < 0 ? (
                  <Ending>
                      <img src="../assets/over.gif" alt="game over" />
                      👿👿👿 GAME OVER 👿👿👿
                  </Ending>
              ) : (
                  <>
                      <QuestionImg src={answer.image} />
                      {options.map((option) => (
                          <OptionBtn onClick={onClickOption}>
                              {option.person}
                          </OptionBtn>
                      ))}
                  </>
              )}
      
  • 심화 과제

    • 1. Portals 을 이용한 Modal을 만들어 봐요! (바깥을 누르면 모달창이 닫혀도 좋을 것 같아요)

      index.html의 root 아래에 portal 요소를 만들어 주었습니다.

      <div id="root"></div>
      <div id="portal"></div>
      

      portal에서 모달 컴포넌트를 렌더링하기 위해Modal.jsx에서 ReactDOM.createPortal() 을 활용하여, children으로 전달해 주었습니다.
      그리고 모달 바깥 또는 X 버튼을 클릭하면 모달이 닫히도록 클릭이벤트를 추가해 주었습니다.

      export default function Modal({ open, children, onClose }) {
          if (!open) return null;
      
          return ReactDom.createPortal(
              <>
                  <ModalBackground onClick={onClose} />
                  <ModalContainer>
                      {children}
                      <CloseBtn onClick={onClose}>X</CloseBtn>
                  </ModalContainer>
              </>,
              document.getElementById("portal")
          );
      }
      
    • 2. 정답을 선택했을 때, 득점했다는 듯한 애니메이션을 자유롭게 넣어주세요!

      Content.jsx에서 confetti을 import하여 정답 선택 시 폭죽이 터지는 애니메이션을 추가하였습니다. 🎉

      import confetti from "https://cdn.skypack.dev/canvas-confetti@1";
      
      // 정답 선택 시 애니메이션
      const onClickAnswer = useCallback(() => {
          confetti({
              particleCount: 150,
              spread: 60,
              zIndex: 1000,
          });
      }, []);
      

🎁 PR Point

  • 뭔가 컴포넌트를 어떤 단위로 나눠야 하는 건지 감이 잘 안잡혔었어요! 이렇게 나누면 되는 게 맞나요?!
  • 배열에 이름을 저장하고, 문제와 선지, 정답을 무작위로 추출해내는 부분이 어려웠는데, 피드백 부탁드립니당!!
  • 이번에 그냥 사진을 고정된 px 크기로 정해서 만들었는데, 모바일 웹 화면으로(vh를 사용해서..?) 만드는 것도 도전해보고 싶어요!ㅎㅎ

😭 소요 시간, 어려웠던 점

  • 2일
  • 사진을 무작위로 섞고 선지도 랜덤으로 출제하는 부분이 제일 어려웠어요 ㅠㅠ 그래서 은형이에게 큰 도움을 받았답니다,,,
  • 진짜 게임처럼 막 애니메이션 이것저것 많이 넣어보려고 했는데 styled-componet를 처음 써보다보니까 생각보다 어려웠어요! 🥲 -> 더 공부해서 추가해볼 예정!!

😎 구현 결과물

화질이슈로 잘안보이는데 클릭해서 봐쥬세욤 ㅎㅎ
video1491466198

@iamphj3 iamphj3 added the 3주차 label Nov 1, 2022
@iamphj3 iamphj3 self-assigned this Nov 2, 2022
Copy link

@myeongheonhong myeongheonhong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

디자인,,,코드,,스타일,,,그대로 그냥 현지'park 드러나네...
미적감각이 한방울이라도 있어야하는 웹프론트개발자로서 반성하고 갑니다..!!
코드도 가독성도 좋은거 같고 특히 랜덤을 이용해서 개발한게 인상적이네요!!
역시 일리네어 최고존엄 OB@!@!@@!!

names.map((name) => ({
person: name,
image: `assets/${name}.jpg`,
}))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

맵을 활용해서 이름과 이미지를 할당하는거 아주 좋군요!!
저도 생각만 했지 적용은 못했는데 적용해봐야겠습니당~~!!
굿굿~!!

setOptions(members.slice(0, 5));
}, [members]);

// 3) onption이 바뀔 때마다 정답 선택 (0~4 중 하나)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onption -> option 인거 같네요!(쓸데없이 철저..^^)

}
// 1) 선지 클릭 후 member 섞기(sort)
// sort()는 음수, 양수, 0의 결과 값에 따라 정렬을 하는데, Math.random() - 0.5는 무작위로 음수, 양수, 0을 리턴하기 때문에 배열이 무작위로 정렬된다. (Math.random()는 0이상 1미만의 숫자를 리턴함)
setMembers((prev) => [...prev].sort(() => Math.random() - 0.5));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오,,,저도 무작위로 멤버나오게 하는 기능을 생각했는데 도대체 어떻게 해야할지 감이 안왔는데 이런식으로 했군요!!
굉장히 좋은정보 알아갑니다!!

@iamphj3 iamphj3 closed this Dec 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants