SVG : Scalable Vector Graphics
확장 가능한 벡터 그래픽, W3C XML의 특수 언어
1. Image Tag + SVG
<img alt="some" src="/images/some.svg" />- flicker 현상
- cache (초기 로딩은 느림, 이미지 변경 시 파라미터 추가)
- 단점: css 불가
2. Inline SVG
- flicker 현상 없음
- first-class in the DOM
- css 가능 : fill, stroke, circle{r: ;cy: ;}, transition
- Event Listeners 가능 (각 요소마다)
- Javscript 동적 제어 가능
- Design Software(Figma, Illustrator)로 merge(mash) 시 색상수정, animation 불가
svg
<svg width="" height="" viewBox="min-x min-y width height"> ... </svg>
- viewBox: internal coordinate system
Line
<line x1="" y1="" x2="" y2="" stroke="" stroke-width="" />
- start point
x1y1/ end pointx2y2
Rectangles
<rect x="" y="" width="" height="" rx="" ry="" fill="" stroke="" stroke-width="" />
- positioned
xy/ growwidthheight/ 반지름 (horizontal, vertical)rxry
- center line (inline or outline으로 설정 불가)
- width 또는 height 0 일때 전체 사라짐 (border 남지 않음)
Circles
<circle cx="" cy="" r="" fill="" stroke="" stroke-width="" />
- 중심점 positioned
cxcy/ 반지름r - 반지름 0 일때 전체 사라짐 (border 남지 않음)
Ellipses
<ellipse cx="" cy="" rx="" ry="" fill="" stroke="" stroke-width="" />
- 중심점 positioned
cxcy/ 반지름 (horizontal, vertical)rxry - 반지름 0 일때 전체 사라짐 (border 남지 않음)
Polygons
<polygon points="x,y x,y x,y" fill="" stroke="" stroke-width="" />
points좌표 나열 (보기 편하게 comma 명시)
,생략해도 최적화에 큰 영향 없음 (web servers gzip compression)
<line x1="10" y1="20" x2="40" y2="20" stroke-width="2" stroke="#2e3f6f" />
<rect x="50" y="20" width="50" height="50" rx="10" ry="10" fill="#879bd7" stroke="#2e3f6f" stroke-width="2" />
<rect x="110" y="20" width="0" height="50" rx="10" ry="10" fill="#87d79b" stroke="#2e3f6f" stroke-width="2" /> // disappear
<circle cx="150" cy="50" r="20" fill="#879bd7" stroke="#2e3f6f" stroke-width="2" />
<ellipse cx="200" cy="50" rx="20" ry="40" fill="#879bd7" stroke="#2e3f6f" stroke-width="2" />
<polygon points="250,20 250,100 300, 20" fill="#879bd7" stroke="#2e3f6f" stroke-width="2" />Path
d: DataM: Move (Start x,y)L: Line(2 Points)
<path
d="
M 10,10 < Move Start
L 90,90 < Line
"
/>Q: Quadratic Bezier curves (3 Points) : 2차 베지어 곡선
<path
d="
M 10,10 < Point 1
Q 10,90 < Point 2 (Curve Point)
90,90 < Point 3
"
/>C: Cubic Bezier curves (4 Points) : 3차 베지어 곡선
<path
d="
M 10,10 < Point 1
C 10,90 < Point 2 (Curve Point 1)
90,10 < Point 3 (Curve Point 2)
90,90 < Point 4
"
/>T: Smooth Quadratic Bezier curves (Q+ 1 point)
S: Smooth Cubic Bezier curves (C+ 2 points)
A: Arcs[rx],[ry] [rotation] [large-arc-flag] [sweep-flag] [end-x],[end-y]- [rx], [ry] 반지름 : 반지름 길이가 시작-끝점 길이보다 짧을 경우에도 비율(rx : ry) 계산하여 그림
- [rotation]
0deg - [large-arc-flag]
0(short path) :1(long path) : 길이가 정확히 같으면 달라지지 않음 - [sweep-flag]
0(counter-clockwise) :1(clockwise) - [end-x], [end-y] 끝점
<path
d="
M 10,20
L 30 20 // 시작점
A 30,30 0 0 0 60,70
"
/>Z: 시작점과 join
<path
d="
M 20,20
A 1,1 0 0 0 60,50
Z
"
fill="none" stroke="#2e3f6f" stroke-width="2"
/>m,l,q,c,t,s,a: 소문자- 상대좌표 (Relative)
Draw Trick
stroke-dasharraystroke-dashoffset속성으로 Draw animation
stroke-dasharray(dash 길이 + 간격) =stroke-dashoffset
element{
stroke-dasharray: 도형 둘레;
animation:elementDraw 3s infinite alternate;
}
@keyframes elementDraw1{
0%{stroke-dashoffset: 0;}
100%{stroke-dashoffset: 도형 둘레;}
}1. 도형 둘레 구한 후 지정 element.getTotalLength()
<polygon points="100,32 116,83 170,83 126,116 144,168 100,135 56,168 73,116 30,83 83,83" fill="none" stroke="#2e3f6f" stroke-width="2" />const polygonLength = document.querySelector('polygon').getTotalLength();
// polygonLength: 544polygon{
stroke-dasharray: 544; //polygonLength
animation:elementDraw1 3s infinite alternate;
}
@keyframes elementDraw1{
0%{stroke-dashoffset: 544;}
100%{stroke-dashoffset: 0;}
}2. 길이 재정의 pathLength
<polygon pathLength="100" points="100,32 116,83 170,83 126,116 144,168 100,135 56,168 73,116 30,83 83,83" fill="none" stroke="#2e3f6f" stroke-width="2" />polygon{
stroke-dasharray: 100; // 실제 길이 544지만 100으로 재정의
animation:elementDraw2 3s infinite alternate;
}
@keyframes elementDraw2{
0%{stroke-dashoffset: 100;}
100%{stroke-dashoffset: 0;}
}3. Inline SVG Sprites
img Sprites 비슷 → img는 HTTP2에서 해결 : 여러 파일 병렬 전송
<defs>나중에 사용할 SVG 그래픽 객체를 저장 (직접 렌더링 되지 않고<use>로 참조하여 렌더링)<symbol>인스턴스화 할 SVG 그래픽 템플릿 객체 정의<use>SVG 문서 내에서 노드를 가져와 복제
예시 1
sprite.svg
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol id="fileAdd">
<path d="M2.5 5V1.5C2.5 1.23478 2.60536 0.98043 2.79289 0.792893C2.98043 0.605357 3.23478 0.5 3.5 0.5H10L13.5 4V12.5C13.5 12.7652 13.3946 13.0196 13.2071 13.2071C13.0196 13.3946 12.7652 13.5 12.5 13.5H7.5" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M3.5 7.5V13.5" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M0.5 10.5H6.5" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>
<symbol id="fileRemove">
<path d="M2.5 7.5V1.5C2.5 1.23478 2.60536 0.98043 2.79289 0.792893C2.98043 0.605357 3.23478 0.5 3.5 0.5H10L13.5 4V12.5C13.5 12.7652 13.3946 13.0196 13.2071 13.2071C13.0196 13.3946 12.7652 13.5 12.5 13.5H6.5" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M0.5 10.5H5.5" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>
</defs>
</svg>index.html
<head>
<link rel="preload" href="sprite.svg" as="image" type="image/svg+xml">
</head>
<svg>
<use href="#fileRemove" />
</svg>preload로 파일 캐시, 성능 향상xmlns:xlink="http://www.w3.org/1999/xlink"SVG는 XML 기반이기 때문에 독립된 SVG파일(sprite.svg)일 경우 최상단에 정의
예시 2 : CustomElements 사용자 정의 요소
k-svg.js
const ksvgSprite = ()=>{
if (document.getElementById('ksvgSprite')) return;
const sprite = document.createElement('div');
sprite.id = "ksvgSprite";
sprite.style.display="none";
sprite.innerHTML=`
<svg>
<defs>
...
</defs>
</svg>
`
document.body.appendChild(sprite);
}
class KSvg extends HTMLElement{
connectedCallback(){
ksvgSprite();
const icon = this.getAttribute('icon');
const size = this.getAttribute('size');
if (!icon || !size) return false;
const numericSize = parseInt(size, 10);
this.style.display = "inline-block"
this.style.width = numericSize + 'px';
this.style.height = numericSize + 'px';
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute('width', numericSize);
svg.setAttribute('height', numericSize);
svg.setAttribute('fill', 'none');
svg.setAttribute('viewBox', `0 0 14 14`);
const use = document.createElementNS("http://www.w3.org/2000/svg", "use");
use.setAttribute("href", `#${icon}`);
use.setAttribute("xlink:href", `#${icon}`);
svg.appendChild(use);
this.appendChild(svg);
}
}
customElements.define('k-svg', KSvg);index.html
<k-svg icon="fileRemove" size="42"></k-svg>