728x90

[Project][SVG] Arc 를 그려보자!


SVG 로 Arc를 그리기 위해서는 path를 사용해야합니다.

path의 d 속성에는 여러개의 명령어가 있는데, 그중 M 과 A 를 이용해 그려보는 react 용 Arc Component를 만들어 봅니다.

https://developer.mozilla.org/ko/docs/Web/SVG/Tutorial/Paths

 

A 명령어


원호를 그릴수 있는 명령어인 A는

A rx ry x축-회전각 큰-호-플래그 쓸기-방향-플래그 x y 로 이루어져있습니다.

rx 는 x축 반지름

ry 는 y축 반지름 입니다.

큰-호-플래그 는 180도를 기준으로 중심각을 결정합니다.

 

M 명령어


M 명령어는 Move To 호를 그릴 시작 좌표를 지정해줍니다.

 

Arc Components


Arc component는 A명령어의 파라미터를 채우기위해 2가지의 유틸성 함수를 사용하고,

parameter로

className = "", id = "", cx, cy, r, startDeg, endDeg, fill = "none", stroke = "#446688", strokeWidth = "2",

를 받습니다.

중심 좌표 cx,cy와 반지름 r, 시작각도 startDeg,끝 각도 endDeg, 원호를 꾸며줄 속성들입니다.

 

get Points


먼저 시작 좌표와 끝좌표를 구해야합니다.

구하기 위해서는 각도를 호도로 변환하여 한 좌표와 반지름을 알고있으므로 cos,sin을 이용해 다른 2좌표를 구합니다.

 

const getPoint=(cx, cy, r, deg)=> {   const rad = ((deg - 90) * Math.PI) / 180.0;    return {     x: cx + r * Math.cos(rad),     y: cy + r * Math.sin(rad),   }; }

 

get Attribute d


이렇게 구한 좌표를 가지고, path 태그의 d속성에 넣어줄 명령어 문자열을 만들어 주어야합니다.

const getAttrD=(cx, cy, r, startDeg, endDeg)=> {   const startPos = getPoint(cx, cy, r, startDeg);   const endPos = getPoint(cx, cy, r, endDeg);   const largeArcFlag = endDeg - startDeg > 180 ? 1 : 0;   return `M${startPos.x},${startPos.y}A${r},${r},0,${largeArcFlag},1,${endPos.x},${endPos.y}`; }

getPoint를 이용해 구한 start Point 와 endPoint를 각각 M과 A에 넣어주고, 나서

largetArcFlag를 구해줍니다.

시작각도와 끝각도의 차이가 180도가 넘어가면 1을 아니면 0을 지정해줍니다.

 

전체 코드


 

// src\project\s\svg\components\arc.js
// modules
import React, { useRef, useEffect, useState, forwardRef } from "react";

const Arc = forwardRef(
  (
    {
      className = "",
      id = "",
      cx,
      cy,
      r,
      startDeg,
      endDeg,
      fill = "none",
      stroke = "#446688",
      strokeWidth = "2",
    },
    ref
  ) => {
    const pathRef = ref || useRef();
    const [d, setD] = useState("");
    useEffect(() => {
      setD(getAttrD(cx, cy, r, startDeg, endDeg));
    }, [cx, cy, r, startDeg, endDeg]);
    return (
      <path
        className={className}
        id={id}
        ref={pathRef}
        d={d}
        fill={fill}
        stroke={stroke}
        strokeWidth={strokeWidth}
      ></path>
    );
  }
);

export default Arc;

const getPoint = (cx, cy, r, deg) => {
  const rad = ((deg - 90) * Math.PI) / 180.0;

  return {
    x: cx + r * Math.cos(rad),
    y: cy + r * Math.sin(rad),
  };
};

const getAttrD = (cx, cy, r, startDeg, endDeg) => {
  const startPos = getPoint(cx, cy, r, startDeg);
  const endPos = getPoint(cx, cy, r, endDeg);
  const largeArcFlag = endDeg - startDeg > 180 ? 1 : 0;
  return `M${startPos.x},${startPos.y}A${r},${r},0,${largeArcFlag},1,${endPos.x},${endPos.y}`;
};

 

추가적으로 forwardRef 를 통해 부모 컴포넌트에서 arc 컴포넌트를 접근할 수 있도록합니다.

 

데모는 아래의 링크에서 확인할 수 있습니다.

http://localhost:8080/work/s/svg

728x90

'project > svg' 카테고리의 다른 글

[Project][SVG] Text를 그려보자!  (0) 2022.07.07

+ Recent posts