본문 바로가기
제니의 개발일지/도움이 되었던 것 정리

[React] SVG 이미지 커스텀, 재사용 하기

by 제니운 2023. 12. 13.
728x90

 

 

 

안녕하세요. 제니입니다!

저번에 통계 도구를 만들게 된 걸 공유하기 시작했는데요!

이번에 지난번에 블로그 포스팅했던 경험과 유사한 경험을 하게 되어 추가 포스팅을 하게 되었습니다.

 

 

전에 카카오톡의 프로필 원 모양인 스쿼클을 SVG로 만들어서 재사용하는 방법을 작성했었는데,

참고용 링크는

 

https://jenny0520.tistory.com/133

 

스쿼클 Squircle css 하는 법 - 트러블 슈팅 기록

디자이너들은 다 안다는 스쿼클 도형은 카카오톡 프로필에 쓰이고 있는 둥근 사각형 모형을 생각하면 된다. 이번에 회사 디자이너님이 웹 사이트에 적용하고 싶어 하셔서, 적용을 하는 과정에

jenny0520.tistory.com

 

 

 

이 링크입니다!

이것과 유사하면서도, 다른 방법으로 작성을 하게 된 내용을 시작하려 합니다.

 

 

 

1-1. 어떻게 사용하려고 하냐면!

 

디자이너님의 이미지

 

 

이런 이미지를 재사용을 할 건데요!

이번에 color picker라는 라이브러리를 사용해서

 

 

 

내가 구현한 color-picker

 

 

 

색상을 선택할 수 있는 기능을 만들었는데,

 

 

 

대략적인 UI

 

 

 

대충 대략적인 UI가 이거라고 가정을 해볼게요! 절대 완성본 아니고 틀만 잡아보았습니다.

이 상태에서, 저는 저기 아이콘을 클릭했을 때 color-picker 모달이 생기고 

color-picker에서 선택한 색상을 표의 색상으로 바꾸려고 합니다!

그 안에서, 추가적으로 표의 색상과 동일하게 아이콘의 색상도 바꿔주고 싶은거에요.

맨 위 사진 보시면 파란색이었던 물감통 모양을 표의 색상과 동일하게 바꾸는 거라고 보시면 됩니다!

 

 

 

1-2. SVG 파일 참고

 

 

 

일단, 디자이너님의 svg 파일을 vs코드에 넣어둡니다.

디자이너님이 없으시고 구글링하신 svg 파일이어도 동일하게 진행됩니다.

 

 

 

이런식으로 넣어두기!

 

 

 

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로 받은 색상 적용하기

 

 

 

return 코드문

 

 

 

이 부분에서, 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 내에 직접 입력하면 되는데

 

 

 

기존에 있던 style 태그

 

 

 

이 태그를 삭제하면 됩니다.

그리고 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 적용

 

 

 

이렇게 직접 적용하지 말고 style을 적용해주면 됩니다.

그런데 위치가 중요해요!

 

 

 

iconStyle 위치

 

 

 

iconStyle 개체 정의를 React 구성 요소 외부로 이동하고 상수로 사용하여 해결할 수 있습니다.

오늘의 svg 변경기록 끄읕 --!

 

 

 

 

728x90