[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 컴포넌트를 접근할 수 있도록합니다.
데모는 아래의 링크에서 확인할 수 있습니다.
'project > svg' 카테고리의 다른 글
[Project][SVG] Text를 그려보자! (0) | 2022.07.07 |
---|