💎 React

[CSS] 리액트 룰렛

ji-hyun 2022. 5. 14. 18:59

 

 

 <div className={classes.wrap}>
   <div className={classes.contents}>
          <div className={classes.rouletteOuter}>
            <div className={clsx(classes.roulette, spinning ? classes.on : "")}> // 룰렛 도전 버튼을 누르면 돌아가는 애니메이션 css 시작
              {/* 값 영역 */}
              <div>
                {prizeData.map((item, i) => {    // data map
                  return (
                    <div
                      style={{ transform: `rotate(${(i + 1) * 45}deg)` }}  // 아이템 배치 각도
                      className={classes.item}
                      key={item.id}
                    >
                      <div>
                        <div>
                          <p className={classes.brandName}>{}</p>
                          <p className={classes.prizeName}>{}</p>
                        </div>
                        <div className={classes.prizeImg}>
                          <img
                            className={classes.prizeImgUrl}
                            src={""}
                            alt="prizeImgUrl"
                          />
                        </div>
                      </div>
                    </div>
                  );
                })}
              </div>
              {/* 선 영역 */}
              <div>
                {[...Array(8)].map((n, index) => {
                  return (
                    <div
                      className={classes.line}
                      style={{
                        transform: `rotate(${(index + 1) * 45 - 22.5}deg)`,  // 선의 각도
                      }}
                      key={index}
                    />
                  );
                })}
              </div>
            </div>
            <FiIcon className={classes.roulettePin} />   // 상단에 있는 룰렛 핀 아이콘
            <div className={classes.rouletteOuterBtn}>
              <button
                className={classes.rouletteBtn}
                onClick={handleClick}
                disabled={
                  // 조건 써주기 (룰렛이 돌아가면 클릭 방지)
                }
              >
                <p>도전</p>
              </button>
            </div>
          </div>
        </div>
      </div>

 

 

import { makeStyles } from "@material-ui/core/styles";
import { StylePropType } from "./Types";

export const useStyles = (props: StylePropType) => {
  return makeStyles(() => ({
  // css 클래스 네임들
   wrap: {
      width: "100vw",
      height: "100vh",
      paddingTop: 80,
      backgroundColor: "#0080f1",
    },
    contents: {
      width: "100%",
      padding: "16px 24px 0",
      color: "#fff",
      position: "relative",
      display: "flex",
      justifyContent: "center",
      alignItems: "flex-start",
    },
    rouletteOuter: {
      position: "relative",
      marginTop: 38,
      width: "95%",
      maxWidth: 327,
      minWidth: 270,
      borderRadius: "50%",
      backgroundColor: "#EAF2FA",
      boxShadow: `0px 12px 20px rgba(0, 0, 0, 0.25)`,
      aspectRatio: "1/1",
    },
    roulette: {
      position: "absolute",
      overflow: "hidden",
      top: "3%",
      left: "3%",
      right: "3%",
      bottom: "3%",
      borderRadius: "50%",
      border: `4px solid #B1C8DE`,
      transformOrigin: "center",
      transitionTimingFunction: "ease-in-out",
      transform: `rotate(${props.rotate})`,   // 룰렛 시작점 세팅
    },
    roulettePin: {
      position: "absolute",
      top: -16,
      left: "50%",
      marginLeft: "-15px",
    },
    item: {
      position: "absolute",
      top: 0,
      left: 0,
      right: 0,
      bottom: 0,
      paddingTop: "10px",
      textAlign: "center",
      display: "flex",
      justifyContent: "center",
      color: "black",
      fontSize: "10px",

      "&:nth-child(1)": {
      // 룰렛 칸 색칠
        background: `conic-gradient(from 337.5deg, #E7EFF3 45deg, #ffffff 45deg 90deg, #E7EFF3 90deg 135deg, #ffffff 135deg 180deg, #E7EFF3 180deg 225deg, #ffffff 225deg 270deg, #E7EFF3 270deg 315deg, #ffffff 315deg)`,
      },
    },
    line: {
      position: "absolute",
      top: 0,
      bottom: "50%",
      left: "50%",
      width: "4px",
      marginLeft: "-2px",
      background: "#B1C8DE",
      transformOrigin: "bottom",
    },
    brandName: {
      fontWeight: 400,
      fontSize: "8px",
      lineHeight: "9px",
      color: "#6B778C",
    },
    prizeName: {
      paddingTop: 3,
      paddingBottom: 8,
      fontWeight: 500,
      fontSize: "10px",
      lineHeight: "11px",
      color: "#1A1A1A",
    },
    prizeImg: {
      width: 45,
      height: 45,
      margin: `5px auto`,
    },
    prizeImgUrl: {
      width: "100%",
      height: "100%",
      objectFit: "cover",
    },
    rouletteOuterBtn: {
      position: "absolute",
      top: "50%",
      left: "50%",
      transform: `translate(-50%, -50%)`,
      width: 92,
      height: 92,
      borderRadius: "50%",
      backgroundColor: "#FFDB00",
      display: "flex",
      alignItems: "center",
      justifyContent: "center",
    },
    rouletteBtn: {
      width: 78,
      height: 78,
      borderRadius: "50%",
      backgroundColor: "#0080F1",
      border: "none",
      color: "#fff",
      fontSize: "18px",
      fontWeight: "bold",
      display: "flex",
      justifyContent: "center",
      alignItems: "center",
      flexDirection: "column",
    },
    "@keyframes ani": {
      // 룰렛 시작점을 써주면 된다.
      from: {
        transform: `rotate(${props.rotate})`,  
      },
      // 룰렛 멈추는 지점을 써주면 된다.
      to: {
        transform: `rotate(calc(${props.nbTurn} * 360deg + (-45deg * ${props.selectedItem})))`,
      },
    },
    on: {
      animationName: "$ani",
      animationDuration: "4s",
      animationFillMode: "forwards",
      animationIterationCount: 1,
      transitionTimingFunction: "ease-in-out",
    },
    // aspectRatio 속성은 IOS14 에서는 적용되지 않기에 media 쿼리를 써주었다.
    "@media": {
      rouletteOuter: {
        aspectRatio: "1/1",
      },
    },
    // 반응형 웹
    "@media (max-width:400px)": {
      rouletteOuter: {
        width: 300,
      },
      prizeName: {
        paddingBottom: 3,
      },
      prizeImg: {
        width: 40,
        height: 40,
      },
      rouletteOuterBtn: {
        width: 80,
        height: 80,
      },
      rouletteBtn: {
        width: 66,
        height: 66,
        fontSize: "15px",
      },
    },
  }));
};

 

 

 

 

 

다음 영상을 참고해 만들었습니다.

 

https://www.youtube.com/watch?v=FBgN0Rdq7zo 

 

 

 

 

'💎 React' 카테고리의 다른 글

리액트 lottie  (0) 2022.05.09
SVG 반응형으로 만들기  (0) 2022.05.09
pakage-lock.json 과 yarn.lock  (0) 2022.05.02
useStyle makeStyle keyframes에다가 props 로 넘겨주는 법  (0) 2022.04.18
react lazy  (0) 2022.03.31