해당 포스트는 인프런 - 1분코딩 SVG 마스터강의를 들으면서 정리한 포스트입니다.
해당 포스트에서 작성한 속성은 대부분
css
에서 적용할 수 있습니다.
확장 가능한 벡터 그래픽
벡터 그래픽: 점과 점 사이의 계산을 이용한 그림
이미지와의 차이점은 픽셀을 사용하는 것이 아닌 계산을 이용해서 그리는 것이므로 크기에 따라서 화질이 변하지 않습니다.
이미지의 경우 화질이 높을수록 픽셀의 수가 많아집니다. 따라서 용량이 고화질일수록 커지게 됩니다.
하지만 SVG
는 크기에 상관없이 현재 크기에 맞게 계산을 통해서 그리는 것이므로 크기에 영향을 받지 않고 항상 좋은 화질을 유지합니다.
하지만 계산이 필요하기 때문에 복잡할수록 용량이 커지게 되기 때문에 간단한 아이콘에 주로 사용합니다.
계산을 통해 그려지기 때문에 html
속성을 변경시키면 그것에 맞게 색상이나 모양을 쉽게 바꿀 수 있습니다.
bakcground-image: url("...경로")
<svg></svg>
<object data="...경로" type="image/svg+xml"></object>
<img src="경로" />
viewBox
: 실제 크기와 관계없이 <svg>
내부에서 보여줄 크기를 지정
아래 예시처럼 선언되어 있다면 실제 <svg>
의 크기는 가로/세로가 400px
입니다.
하지만 <svg>
내부에서 그려지는 크기는 가로/세로가 200px
이라고 생각하고 그려지기 때문에 <rect>
는 50px
의 크기로 그려지게 됩니다.
실제 크기는 400px
, <svg>
의 내부에서 그려지는 크기는 200px
400px
의 도화지에 100px
짜리 사각형을 그리라고 했으나, 실제로는 200px
의 도화지이기 때문에 50px
로 축소해서 그립니다.
<svg
width="400"
height="400"
viewBox="0 0 200 200"
>
<rect x="0" y="0" width="100" height="100" />
</svg>
<defs>
: 나중에 사용할 그래픽 객체, css, js들을 작성하는 공간
<defs>
내부에서의 작성 방식은 html
에서 inline
으로 작성하던 방식대로 작성하면 됩니다. ( <style>
, <script>
)
<svg
id="face"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px"
y="0px"
viewBox="0 0 40 40"
>
<defs>
<style>
@keyframes eye-ani {
100% {
transform: scaleY(0.2);
}
}
#eye.start {
transform-origin: 50%;
animation: eye-ani 0.5s infinite alternate;
}
</style>
<script>
window.addEventListener("DOMContentLoaded", () => {
const $face = document.querySelector("#face");
$face.addEventListener("click", () => {
const $eye = document.querySelector("#eye");
$eye.classList.toggle("start");
});
});
</script>
</defs>
<path id="contour" d="M20,8c6.6,0,12,5.4,12,12s-5.4,12-12,12S8,26.6,8,20S13.4,8,20,8 M20,6C12.3,6,6,12.3,6,20s6.3,14,14,14s14-6.3,14-14
S27.7,6,20,6L20,6z"/>
<g id="eye">
<path d="M14,18c-1.1,0-2,0.9-2,2s0.9,2,2,2s2-0.9,2-2S15.1,18,14,18L14,18z"/>
<path d="M26,18c-1.1,0-2,0.9-2,2s0.9,2,2,2s2-0.9,2-2S27.1,18,26,18L26,18z"/>
</g>
<path id="mouth" d="M28.3,24.6c-1.7,3-4.9,4.9-8.3,4.9s-6.6-1.9-8.3-4.9l-0.9,0.5c1.9,3.3,5.4,5.4,9.2,5.4c3.8,0,7.3-2.1,9.2-5.4
L28.3,24.6z"/>
<path id="hair" class="st0" d="M30.8,8.1c-0.9-2-3.6-3.5-6.8-3.5c-0.3,0-0.5,0-0.8,0c-1.2-0.6-2.7-1-4.4-1c-1.6,0-3.2,0.4-4.4,1
c-0.3,0-0.6,0-0.9,0c-3.4,0-6.3,1.7-7,3.9C4.2,9.4,2.6,11.1,2.6,13c0,2.8,3.2,5,7.2,5c1.9,0,3.5-0.5,4.8-1.3c0.1,0,0.2,0,0.3,0
c1.3,0.7,2.9,1.2,4.7,1.2c1.9,0,3.6-0.5,4.9-1.4c1.3,0.9,3.1,1.5,5.1,1.5c4,0,7.2-2.2,7.2-5C36.8,10.5,34.2,8.5,30.8,8.1z"/>
</svg>
속성을
inline-style
로 사용하지 않고css
(<style>
orxxx.css
파일 )을 이용해서 지정할 수 있습니다.
우선순위css
>inline-style
x
, y
: 시작점 위치width
, height
: 사각형 크기fill
: 색상stroke
: 테두리 색상stroke-width
: 테두리 굵기stroke-linecap
: 선의 마무리 형태 ( butt
, round
, square
)stroke-linejoin
: 모서리 형태 ( miter
, round
, bevel
)<rect>
)rx
, ry
: 모서리 둥글림 정도<svg width="600" height="400" style="background-color: #ddd;">
<rect
x="40"
y="40"
width="200"
height="200"
fill="purple"
stroke="black"
stroke-width="20"
stroke-linejoin="round"
rx="20"
ry="40"
/>
</svg>
<circle>
)cx
, cy
: 원의 중점r
: 반지름<svg width="600" height="400" style="background-color: #ddd;">
<circle
cx="400"
cy="120"
r="80"
fill="purple"
stroke="black"
stroke-width="20"
/>
</svg>
<ellipse>
)cx
, cy
: 원의 중점rx
, ry
: x/y축 반지름<svg width="600" height="400" style="background-color: #ddd;">
<ellipse
cx="400"
cy="320"
rx="30"
ry="60"
fill="purple"
stroke="black"
stroke-width="20"
/>
</svg>
<line>
)x1
, x2
: x축의 시작/끝 점y1
, y2
: y축의 시작/끝 점<svg width="600" height="400" style="background-color: #ddd;">
<line
x1="100"
x2="200"
y1="300"
y2="350"
stroke="purple"
stroke-width="20"
/>
</svg>
<polyline>
)points
: x, y축의 시작과 끝점들을 ,
로 구분해서 작성<svg width="600" height="400" style="background-color: #ddd;">
<polyline
points="20 260, 20 370, 250 370, 220 280"
stroke="blue"
stroke-width="20"
fill="transparent"
/>
</svg>
<ploygon>
)points
: x, y축의 시작과 끝점들을 ,
로 구분해서 작성<svg width="600" height="400" style="background-color: #ddd;">
<ploygon
points="20 260, 20 370, 250 370, 220 280"
stroke="blue"
stroke-width="20"
fill="transparent"
/>
</svg>
<path>
)d
M
: 시작점L
: 직선 ( 시작점, 끝점 )H
: 가로 직선 ( 이동할 x
위치 )V
: 세로 직선 ( 이동할 y
위치 )Z
: 현재 위치와 시작점 잇기C
: 곡선 ( 시작점, 휘어짐 정도, 끝점 )<svg width="600" height="400" style="background-color: #ddd;">
<path
d="M300 200 L 500 100 H 200 V 200 Z C 350 250, 200 300, 400 300"
stroke="blue"
stroke-width="10"
fill="transparent"
/>
</svg>
x
, y
: 시작과 끝위치<svg width="600" height="400" style="background-color: #ddd;">
<text
x="20"
y="100"
font-size="2rem"
font-weight="bold"
fill="blue"
>
Hello, SVG
</text>
</svg>
<linearGradient>
: 직선 형태의 그레디언트 ( 좌 -> 우 )<radialGradient>
: 원형 형태의 그레디언트 ( 상, 하, 좌, 우 -> 중간 )<svg width="600" height="400" style="background-color: #ddd;">
<defs>
<linearGradient id="my-gradient">
<stop offset="0%" stop-color="red" />
<stop offset="50%" stop-color="green" />
<stop offset="100%" stop-color="blue" />
</linearGradient>
</defs>
<text
x="20"
y="100"
font-size="2rem"
font-weight="bold"
fill="url(#my-gradient)"
>
Hello, SVG
</text>
</svg>
<pattern>
)반복할 요소의 크기 * 반복 횟수 ===
<svg>
의 크기가 맞지 않으면 의도한 모양의 패턴과 다른 모양이 됩니다.
아래 예시는 원크기(80) * 반복 횟수(10) ===<svg>
크기(800)
x
, y
: 패턴의 시작 위치width
, height
: 가로/세로 반복할 개수 ( 1: 1개, 0.5: 2개, 0.1: 10개 ... )<pattern> 내부
: 반복할 요소<svg width="100%" height="100%" viewBox="0 0 800 800" style="background-color: #ddd;">
<defs>
<pattern
id="my-pattern"
x="0"
y="0"
width="0.1"
height="0.1"
>
<circle cx="40" cy="40" r="40" fill="blue" />
</pattern>
</defs>
<rect
x="0"
y="0"
width="100%"
height="100%"
fill="url(#my-pattern)"
/>
</svg>
<mask>
)특정 영역만 보이게 하는 효과입니다.
<mask>
내부의 요소가 흰색에 가까울수록 진하게 보이게 됩니다.
<svg
x="0"
y="0"
width="100%"
height="100%"
viewBox="0 0 400 400"
>
<defs>
<mask id="my-mask">
<circle id="circle" cx="20" cy="80" r="60" fill="#fff"/>
</mask>
<style>
@keyframes move {
0% { cx: 20; }
100% { cx: 140; }
}
#circle {
animation: move 1s infinite alternate;
}
</style>
</defs>
<g mask="url(#my-mask)">
<text x="20" y="40" font-size="2rem" font-weight="bold" fill="red">
Hello, SVG
</text>
<text x="20" y="80" font-size="2rem" font-weight="bold" fill="green">
Hello, Next.js
</text>
<text x="20" y="120" font-size="2rem" font-weight="bold" fill="blue">
Hello, Velog
</text>
</g>
</svg>
<tspan>
)<svg width="600" height="400" style="background-color: #ddd;">
<text
x="20"
y="100"
font-size="2rem"
font-weight="bold"
fill="blue"
>
Hello, <tspan fill="green">SVG</tspan>
</text>
</svg>
<textPath>
)<svg width="1000" height="800" style="background-color: #ddd;">
<defs>
<path
id="my-text"
d="M 50 400 C 50 400, 300 500, 400 400 C 400 400, 600 170, 700 300"
fill="transparent"
stroke="red"
stroke-width="10"
/>
</defs>
<text
x="20"
y="100"
font-size="2rem"
font-weight="bold"
fill="blue"
>
<textPath href="#my-text">
Hello, SVG Lorem ipsum dolor, sit amet consectetur
</textPath>
</text>
</svg>
svg
는 대부분 툴을 이용해서 만들어진 상태로 사용하기 때문에 직접적으로 코드를 작성하거나 수정할 경우는 거의 없다고 생각합니다.
저도 heoricon, fontawesome 같은 사이트에서 사용할 아이콘을 찾아서 복사 붙여넣기를 이용해서 사용했지만 사용했습니다.
하지만 이게 어떤 코드인지 모르고 사용했기 때문에 불안했기도 했고, 아이콘에서 색상, 크기, 애니메이션 같은 작은 부분을 수정하는데도 검색을 통해서 찾고 테스트하는 과정을 계속하면서 그때만 대충 이해하고 넘어갔던 부분을 하나하나 공부하면서 원리를 이해할 수 있어서 도움이 많이 됐습니다.
물론 위의 코드들을 모두 외우거나 실제로 작성하는 일은 없겠지만 최소한 어떤 코드에 어떤 동작을 하는지 얕게 이해하고 있으니 다음 문제가 생겼을 때 시간 낭비를 줄이고 금방 해결할 수 있을 것 같습니다.