<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 |