안녕하세요. 제니입니다!
저번에 통계 도구를 만들게 된 걸 공유하기 시작했는데요!
이번에 지난번에 블로그 포스팅했던 경험과 유사한 경험을 하게 되어 추가 포스팅을 하게 되었습니다.
전에 카카오톡의 프로필 원 모양인 스쿼클을 SVG로 만들어서 재사용하는 방법을 작성했었는데,
참고용 링크는
https://jenny0520.tistory.com/133
이 링크입니다!
이것과 유사하면서도, 다른 방법으로 작성을 하게 된 내용을 시작하려 합니다.
1-1. 어떻게 사용하려고 하냐면!
이런 이미지를 재사용을 할 건데요!
이번에 color picker라는 라이브러리를 사용해서
색상을 선택할 수 있는 기능을 만들었는데,
대충 대략적인 UI가 이거라고 가정을 해볼게요! 절대 완성본 아니고 틀만 잡아보았습니다.
이 상태에서, 저는 저기 아이콘을 클릭했을 때 color-picker 모달이 생기고
color-picker에서 선택한 색상을 표의 색상으로 바꾸려고 합니다!
그 안에서, 추가적으로 표의 색상과 동일하게 아이콘의 색상도 바꿔주고 싶은거에요.
맨 위 사진 보시면 파란색이었던 물감통 모양을 표의 색상과 동일하게 바꾸는 거라고 보시면 됩니다!
1-2. SVG 파일 참고
일단, 디자이너님의 svg 파일을 vs코드에 넣어둡니다.
디자이너님이 없으시고 구글링하신 svg 파일이어도 동일하게 진행됩니다.
svg 파일을 클릭하게 되면
이렇게 코드를 확인할 수 있는데요!
이 내용을 그대로 복사해주세요.
1-3. 재사용 목적의 파일 만들기
import React, { useEffect } from 'react';
const CustomIcon = () => {
return (
<svg id="mySvg" xmlns="http://www.w3.org/2000/svg" width="34" height="34" viewBox="0 0 34 34">
<defs>
<style>
{`.a{fill:#fff;stroke:#fec301;opacity:0;}.b,.e{fill:none;}
.b{stroke:#000;}.c{fill:#0000ff;}.d{stroke:none;}`}
</style>
</defs>
<g className="a">
<rect className="d" width="34" height="34" rx="3" />
<rect className="e" x="0.5" y="0.5" width="33" height="33" rx="2.5" />
</g>
<g transform="translate(-724.793 -324.085)">
<rect width="16" height="2" transform="translate(734 350)" />
<g transform="translate(270.376 -326.632) rotate(30)">
<g className="b" transform="translate(735.087 334.775)">
<rect className="d" width="13" height="13" />
<rect className="e" x="0.5" y="0.5" width="12" height="12" />
</g>
<rect width="3" height="1" transform="translate(733.587 334.775)" />
</g>
<path className="c" d="M740.953,342.047l9.563,5.56,3.194-5.56Z" transform="translate(-6.524 -0.342)" />
<path className="c" d="M799.563,1739.079a1.614,1.614,0,0,1-3.227,0c0-.891,1.614-2.715,1.614-2.715S799.563,1738.188,799.563,1739.079Z" transform="translate(-47.336 -1394.659)" />
</g>
</svg>
);
};
export default CustomIcon;
이렇게 컴포넌트를 만들고 return 문 안에 복사한 svg 코드를 붙여넣어주세요.
1-3-1. class → className 변경
기존 파일에 class 라고 코드가 되어 있다면,
Type '{ children: Element[]; class: string; }' is not assignable to type 'SVGProps<SVGGElement>'.
Property 'class' does not exist on type 'SVGProps<SVGGElement>'. Did you mean 'className'?
이런식의 에러가 발생될 거에요.
에러 내용과 동일하게 class 되어 있는 부분을 className이라고 바꾸어줍니다.
1-3-2. 재사용하는 색상 적용하기
import React, { useEffect } from 'react';
interface CustomIconProps {
selectedColor: string;
}
const CustomIcon = ({selectedColor}: CustomIconProps) => {
// 위 코드랑 똑같습니다.
);
};
export default CustomIcon;
1-3-3. props로 받은 색상 적용하기
이 부분에서, fill: #0000ff 이라고 되어 있는 부분 보이시죠.
이 fill 채우는 속성 색상을
<defs>
<style>
{`.a{fill:#fff;stroke:#fec301;opacity:0;}.b,.e{fill:none;}
.b{stroke:#000;}.c{fill:${selectedColor}}.d{stroke:none;}`}
</style>
</defs>
이렇게 바꿔주면, props로 전달할 수 있게 됩니다.
1-4. 실제 사용할 때
<CustomColorSelectIcon
selectedColor={statData.dataColors[colIndex]}
/>
이렇게, 원하는 색상을 넣어주게 되면, 원활하게 변경할 수 있습니다!
그럼 디자이님이 별도로 색상을 주시지 않아도 되고
특히 표 색상을 바꿈과 동시에 svg 컬러도 변경되기 때문에 UI의 고도화를 진행할 수 있게 됩니다.
1-5. 만약, 한 페이지내에서 동일한 파일을 여러번 사용할 경우
위 링크 남겨드렸던 지난 번 포스팅과 동일하게,
svg 파일에서 동일한 id 라고 인식을 하게 되면, 각각 props 를 따로 주어도 한 색상으로만 바뀌게 됩니다.
비슷한 현상으로 useRef를 사용했을 때, 잘못 적용하게 되면 하나의 영역으로 인식되는 것과 동일한 느낌입니다.
지난번 포스팅에선 스쿼클의 경우, clip 을 하기 때문에 clipPath를 변경하는 구조였는데
이번엔 clip이 없고 색상만 변경하기 때문에 다른 방식으로 접근 해야 합니다.
그럴 경우, style 태그를 지우고 path 내에 직접 입력하면 되는데
이 태그를 삭제하면 됩니다.
그리고 svg 코드 맨 아래에 있던 <path/> 부분에
props로 받았던 selectedColor를 fill로 해서 넣어주게 되면, clipPath처럼 id를 따로 주지 않아도 적용됩니다!
2-1. 아이콘에 추가 작업이 있을 때
아이콘을 클릭했을 때 모달을 띄우거나, 함수를 넣고 싶으면 동일하게 props로 넘기는 형식을 사용하면 됩니다.
2-1-1. onClick 기능
interface CustomIconProps {
selectedColor: string;
onClick: () => void;
}
const CustomIcon = ({selectedColor, onClick}: CustomIconProps) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="34"
height="34"
viewBox="0 0 34 34"
onClick={onClick}
>
// 아래 동일합니다.
onClick을 추가적으로 넣어주고
사용하는 곳에서도 onClick을 넣어주게 되면 함수 적용도 바로 가능합니다!
svg에 적용할 수 있어요.
2-1-2. style 추가하기
onClick을 넣으니까 cursor:pointer style을 넣고 싶었거든요.
그것도 동일하게 svg 에 추가해주면 되는데
<svg
xmlns="http://www.w3.org/2000/svg"
width="34"
height="34"
viewBox="0 0 34 34"
style={{ cursor: 'pointer' }}
onClick={onClick}
>
이렇게 style을 직접 입력하게 되면
jsx attribute values should not contain objects created in the same scope
와 같은 eslint 이슈를 만날 수 있습니다.
그럴 땐,
const iconStyle = { cursor: 'pointer' };
이렇게 직접 적용하지 말고 style을 적용해주면 됩니다.
그런데 위치가 중요해요!
iconStyle 개체 정의를 React 구성 요소 외부로 이동하고 상수로 사용하여 해결할 수 있습니다.
오늘의 svg 변경기록 끄읕 --!
'제니의 개발일지 > 도움이 되었던 것 정리' 카테고리의 다른 글
[React] 화면 저장, 캡쳐 기능 구현하기(TypeScript) (1) | 2024.02.26 |
---|---|
[ngrok] Invalid Host header 에러 해결법 (0) | 2024.01.03 |
[React] TypeScript로 표 만드는 라이브러리 추천 (0) | 2023.12.01 |
JavaScript 절댓값 변환 (0) | 2023.11.23 |
[react-calendar] 프로젝트에 달력 적용하기 TypeScript, react-calendar webpack 문제 해결 (2) | 2023.11.01 |