이미지를 동적으로 입히는 기능은 생각보다 단순했다.
이제는 사용자가 선택한 아이템들이 서버단에 저장이 되어, 새로고침 시나 로그아웃 후에 다시 로그인하여도 선택했던 아바타의 이미지가 나와야 한다.
우리가 정한 카테고리는 총 4가지로 좁혀봤다.
- 눈 (Eye)
- 입 (Mouth)
- 머리 (Hair)
- 배경 (Back)
해야할 순서
- 사용자가 여러 아이템들을 선택할 수 있는 슬라이드를 만들어준다.
- 슬라이드에 이미지들을 뿌려주기 위해, map함수를 사용해야하니 이미지파일규칙이 정해져야 한다.
- 슬라이드에서 선택한 아이템이 위 캐릭터에 반영이 되어야한다. (변수값이 공유되야함)
- 각종 카테고리별로 변수를 만들어, 선택된 아이템의 변수 값을 db로 쏴주어야한다.
- 여러 아이템들중, 하나만 선택했을 경우에도 정상작동해야한다. (조건문으로 할 지?_)

위와 같이, 이미지를 불러와서 아이템 선택창을 우선적으로 만들어주어야한다.
일일이 박스를 만들어 이미지경로를 정해주기는 너무 힘이드니, 일종의 파일이름에 규칙을 만들어 map함수를 사용해보려한다.
아래와 같은 방식으로 이름을 정하면 어떨까?
Eyewear_1
Eyewear_2
Eyewear_3
Eyewear_4
Eyewear_5
Eyewear_6
Eyewear_7
카테고리_순서.png 이런식으로 이름이 정해지면, db로 보낼때도 앞부분 카테고리와 순서를 보내면 되니 map함수를 돌릴때에도 간편할 것 같다.
그렇다면, 슬라이드에서 선택된 아이템이 캐릭터창에도 반영이 되게 props로 전달하면 될 것 같다.
import { style } from "@mui/system";
import React, { useState } from "react";
import AvatarBox from "./AvatarBox";
import styled from "styled-components";
const AvatarSelect = () => {
//*초기 카테고리는 눈으로 고정
const [selectCategory, SetSelectCategory] = useState("Eye");
//! 이런식으로 user avatar가 db에 저장되면 된다!
const userAvatar = { Eye: 1, Hair: 1, Mouth: 1, Back: 1 };
const [userSelect, setUserSelect] = useState(userAvatar);
const ImgList = [
{ Num: 1, Category: "Eye" },
{ Category: "Mouth", Num: 1 },
{ Category: "Mouth", Num: 2 },
{ Category: "Mouth", Num: 3 },
{ Category: "Mouth", Num: 4 },
{ Category: "Mouth", Num: 5 },
{ Category: "Mouth", Num: 6 },
{ Category: "Eye", Num: 3 },
{ Category: "Back", Num: 4 },
{ Category: "Eye", Num: 1 },
{ Category: "Hair", Num: 2 },
];
console.log(userSelect);
return (
<Wrap>
<AvatarBox userSelect={userSelect} />
<AvatarSelectCtn>
<AvatarCategory>
<div
className={selectCategory === "Eye" ? "selected" : undefined}
onClick={() => SetSelectCategory("Eye")}
>
눈
</div>
<div
className={selectCategory === "Mouth" ? "selected" : undefined}
onClick={() => SetSelectCategory("Mouth")}
>
입
</div>
<div
className={selectCategory === "Hair" ? "selected" : undefined}
onClick={() => SetSelectCategory("Hair")}
>
머리
</div>
<div
className={selectCategory === "Back" ? "selected" : undefined}
onClick={() => SetSelectCategory("Back")}
>
배경
</div>
</AvatarCategory>
<AvatarItemCtn>
{ImgList.map((Img) => {
if (Img.Category == selectCategory)
return (
<ImgItem
onClick={() =>
setUserSelect({ ...userSelect, [Img.Category]: Img.Num })
}
>
{Img.Category}_{Img.Num}
</ImgItem>
);
})}
</AvatarItemCtn>
</AvatarSelectCtn>
</Wrap>
);
};
export default AvatarSelect;
부모 컴포넌트에서 이러한 식으로, 이미지를 클릭하면 해당 카테고리의 숫자를 state값에 넘겨주고 자식컴포넌트에 넘겨준다. (객체의 키값을 동적으로 할당하기위해 빈 배열로 키값을 감싸줌)
객체에 키값 동적으로 할당하기
객체로 만들 부분을 빈 배열로 만들고 [ ]방식으로 프로퍼티를 설정하는 방법을 이용하면 키 값을 동적으로 설정 할 수 있습니다. var keyname = "my"; var postfix = "Age"; var value = 27; var something = {}; somethi
haardy.tistory.com
여기서 자식컴포넌트는 아바타가 보여지는 박스이다. 그props를 받은 아바타박스는 이미지경로를 다시 설정하여 바뀐 아이템을 보여준다.
아래는 자식컴포넌트의 코드이다.
import React, { useState } from "react";
import styled from "styled-components";
const AvatarBox = ({ userSelect }) => {
const [Face, setFace] = useState(1);
console.log(userSelect);
const { Eye, Hair, Mouth, Back } = userSelect;
console.log(Mouth);
return (
<AvatarCtn>
<BackCtn Back={Back}>
{" "}
<FaceCtn Face={Face}>
<HairCtn Hair={Hair} />
<EyeCtn Eye={Eye} />
<MouthCtn Mouth={Mouth} />
</FaceCtn>
</BackCtn>
</AvatarCtn>
);
};
export default AvatarBox;
생각보다 간단하게 끝났다. 이때까지 잘 다루지 못한 이미지를 다룬다는 생각에 괜시리 어렵다 생각이 들었던 것 같다.
여기서 주목할만한 점은, background-image의 url을 변수를 활용해 동적으로 이미지 경로를 관리하는 것이다.

아직 이미지를 많이 만들어 놓지않아서, 선글라스 한 개랑 입술 두 개밖에 없지만 잘 구동하는 것을 볼 수 있다!
'프로젝트 > 보드윗 (보드게임원 매칭 서비스)' 카테고리의 다른 글
[ 항해99 실전프로젝트 ] 로고를 SVG로 다루어보자! (1) (0) | 2022.11.21 |
---|---|
[ 항해99 실전프로젝트 ] 디테일페이지를 모달창으로 바꾸기 (0) | 2022.11.21 |
[ 항해99 실전프로젝트 ] 회원가입페이지 나누기 (0) | 2022.11.20 |
[ 항해 99 실전프로젝트 ] 이미지 입히기 테스트 ( 2 ) (0) | 2022.11.19 |
[ 항해99 실전프로젝트 ] 아바타 페이지를 만들어보자 ( 1 ) (0) | 2022.11.19 |