๐Ÿ‘ฉ‍๐Ÿ’ป/Web

[SVG] JavaScript, CSS๋ฅผ ํ™œ์šฉํ•œ Path ๊ธฐ๋ฐ˜ ํ…์ŠคํŠธ ์• ๋‹ˆ๋ฉ”์ด์…˜

ํ•œ๋‚˜ 2021. 1. 30. 02:23

 

 

์œ„์ฒ˜๋Ÿผ ํ…์ŠคํŠธ์˜ path๋ฅผ ๋”ฐ์„œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ฃผ๋Š” ์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค์–ด๋ดค๋‹ค.

ํ”„๋กœํ† ํƒ€์ดํ•‘ ํˆด๋กœ ์ž˜ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” figma๋กœ ๊ธฐ๋ณธ์ด ๋˜๋Š” SVG๋ฅผ ๋งŒ๋“ค๊ณ , ๊ฐ„๋‹จํ•œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์™€ CSS๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋งŒ๋“ค์—ˆ๋‹ค.

 

SVG ํƒœ๊ทธ ์ƒ์„ฑ

 

figma๋กœ ์•„๋ฌด draft๋‚˜ ์—ด์–ด์„œ ์บ”๋ฒ„์Šค๋ฅผ ๋งŒ๋“  ๋‹ค์Œ, T ์•„์ด์ฝ˜์„ ๋ˆŒ๋Ÿฌ ํ…์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. figma์—์„œ ํ•œ๊ธ€์€ ๋ฐ›์นจ์„ ํƒ€์ดํ•‘ํ•  ๋•Œ ๋ฌธ์ œ๊ฐ€ ์žˆ์–ด์„œ, ํ•œ๊ตญ์–ด ํ…์ŠคํŠธ๋กœ SVG ์†Œ์Šค๋ฅผ ์ค€๋น„ํ•ด์•ผ ํ•œ๋‹ค๋ฉด, ํฌํ† ์ƒต ๋“ฑ ๋‹ค๋ฅธ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋‚ซ๋‹ค.

 

์ด๋ ‡๊ฒŒ ์•„๋ฌด ํ…์ŠคํŠธ ๋ฐ•์Šค๊ฐ€ ์ƒ์„ฑ๋˜๊ณ , ํ˜„์žฌ๋Š” Path๋ฅผ ๋”ฐ์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ ํŒŒ๋ž€์ƒ‰ ํ…Œํˆฌ๋ฆฌ๊ฐ€ ํ…์ŠคํŠธ ๋ฐ•์Šค ์ „์ฒด์— ๊ฑธ์ณ ์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

์—ฌ๊ธฐ์„œ ์šฐํด๋ฆญ -> outline stroke๋ฅผ ๋ˆŒ๋Ÿฌ์ฃผ๊ณ ,

 

 

์ด ์ƒํƒœ์—์„œ ์˜ค๋ฅธ์ชฝ์˜ Design ํŒจ๋„์˜ Stroke ๋‚˜ Fill ์— ์—ฌ๋Ÿฌ ์„ค์ •๊ฐ’์„ ์ฃผ์–ด ๋””์ž์ธํ•œ๋‹ค. ๋‚˜๋Š” Fill์€ ์‚ญ์ œํ•ด์ฃผ๊ณ , Stroke์˜ width๋ฅผ 7๋กœ, ๋ฐ”ํƒ• ์ƒ‰์„ ํฐ์ƒ‰์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ์—ˆ๋‹ค.

 

์„ค์ •์„ ๋งˆ์น˜๊ณ  ๋‚˜๋ฉด, code editor์— ๋ถˆ๋Ÿฌ์™€ ๋ถ™์—ฌ๋„ฃ์–ด์ฃผ๋ฉด ์•„๋ž˜์ฒ˜๋Ÿผ <svg> ํƒœ๊ทธ ์•ˆ์— <mask> .. <rect> .. <path> ์ˆœ์œผ๋กœ ์ž˜ ์†Œ์Šค๊ฐ€ ๋ณต์‚ฌ๋œ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ๋ฌผ๋ก  ์–ด๋–ค ํ˜•ํƒœ๋ฅผ ๋งŒ๋“œ๋Š๋ƒ์— ๋”ฐ๋ผ ํƒœ๊ทธ๋Š” ์ƒ์ดํ•  ์ˆ˜ ์žˆ๋‹ค.

 

SVG Path Animation ๋งŒ๋“ค๊ธฐ

body {
  margin: 0;
  padding: 0;
  background-color: #e7dcc2;
}

#logo {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

ํ•˜์–€์ƒ‰ ๊ธ€์ž๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ, ์œ„์ฒ˜๋Ÿผ ๊ธฐ๋ณธ CSS๋ฅผ ์ž‘์„ฑํ•ด์ฃผ๊ณ , ์ด์ œ getTotalLength()๋ฅผ ์ด์šฉํ•ด ๊ฐ Path์˜ ์ „์ฒด ๊ธธ์ด๋ฅผ ๊ฐ€์ง€๊ณ  ์˜ฌ ์ฐจ๋ก€์ด๋‹ค.

 

์šฐ์„  ์ „์ฒด์ ์ธ HTML ํ˜•ํƒœ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

 

 

๊ตฌ์กฐ๋ฅผ ๋ณด๋ฉด <svg> ์•ˆ์— <mask>, <rect>, <path> ์ˆœ์ธ๋ฐ, ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋™์ž‘์‹œํ‚ฌ path๋Š” <mask> ํƒœ๊ทธ๊ฐ€ ๋๋‚˜๊ณ  ๋‚œ ๋‹ค์Œ์˜ ์ด 4๊ฐœ์˜ <path> ํƒœ๊ทธ์ด๋‹ค. ์–ด๋–ค ํ…์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š๋ƒ์— ๋”ฐ๋ผ ์ด <path> ํƒœ๊ทธ์˜ ์ˆ˜๋Š” ๋‹ฌ๋ผ์ง„๋‹ค.

๊ฐ๊ฐ์˜ path ํƒœ๊ทธ์—๋Š” myPath๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ์จ์ฃผ์—ˆ๊ณ , <svg>์—๋Š” logo ์•„์ด๋””๋ฅผ ๋ถ€์—ฌํ–ˆ๋‹ค.

const logo = document.querySelectorAll("#logo .myPath");

for(let i = 0; i < logo.length; i++) {
    console.log(`${i+1}๋ฒˆ์งธ path์˜ ์ด ๊ธธ์ด ${logo[i].getTotalLength()}`);
}
float someElement.getTotalLength();

path์˜ ์ด ๊ธธ์ด๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด querySelectorAll๋กœ ์ „์ฒด node๋ฅผ ๊ฐ€์ง€๊ณ  ์™”๋‹ค. for๋ฌธ์„ ๋Œ๋ ค i๋ฒˆ์งธ ๋…ธ๋“œ์˜ ์ „์ฒด path ๊ธธ์ด๋ฅผ ๊ฐ€์ง€๊ณ  ์˜ค๋Š” getTotalLength() ๋ฉ”์†Œ๋“œ๋ฅผ ์“ด๋‹ค. ๊ฐœ๋ฐœ์ž ๋„๊ตฌ๋ฅผ ์—ด์–ด๋ณด๋ฉด ์•„๋ž˜์ฒ˜๋Ÿผ ์ „์ฒด ๊ธธ์ด๊ฐ€ ๋ฐ˜ํ™˜๋˜์–ด ์˜จ๋‹ค.

 

 

 

๋‹ค์‹œ CSS ํŒŒ์ผ๋กœ ๋Œ์•„์™€, ๊ฐ๊ฐ์˜ ๊ธ€์ž์— ์–ด๋–ป๊ฒŒ stroke ๋ณ€ํ™”๋ฅผ ์ค„ ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ์•„๋ณด๊ธฐ ์œ„ํ•ด nth-child ๋˜๋Š” nth-of-type์„ ์จ #logo ์•„๋ž˜์˜ .myPath๋ฅผ ํ•˜๋‚˜ ํ•˜๋‚˜ ์„ ํƒํ•ด์ค€๋‹ค.

 

nth-of-type()๊ณผ nth-child() ๋น„๊ต

/* nth-of-type์„ ์“ธ ๊ฒฝ์šฐ */

#logo .myPath:nth-of-type(1) {
}

#logo path:nth-of-type(2) {
}

#logo .myPath:nth-of-type(3) {
}

#logo .myPath:nth-of-type(4) {
}

/* nth-child๋ฅผ ์“ธ ๊ฒฝ์šฐ */

#logo path:nth-child(2) {
}
#logo path:nth-child(3) {
}
#logo path:nth-child(4) {
}
#logo path:nth-child(5) {
}

 

ํ˜„์žฌ html ํƒœ๊ทธ์˜ <svg> ๋‚ด๋ถ€๋ฅผ ๋ณด๋ฉด <mask> ํƒœ๊ทธ ๊ทธ๋ฆฌ๊ณ  4๊ฐœ์˜ <path> ํƒœ๊ทธ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค. nth-child๋Š” ์„œ๋กœ ๋™๋“ฑํ•œ ์œ„์น˜์˜ ํƒœ๊ทธ๋“ค ๋‚ด์—์„œ์˜ ์ˆœ์„œ๋ฅผ ์งš๊ธฐ ๋•Œ๋ฌธ์—, #logo์˜ path์˜ nth-child()๋ฅผ ์“ธ ๊ฒฝ์šฐ mask ํƒœ๊ทธ๋ฅผ ์„ผ ๋‹ค์Œ 2๋ฒˆ์งธ์— ๋“ฑ์žฅํ•˜๋ฏ€๋กœ ์ˆซ์ž๊ฐ€ 2๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๊ฒŒ ๋œ๋‹ค.

 

nth-of-type์„ ์“ธ ๊ฒฝ์šฐ์—๋Š” ๊ฐ™์€ ์ข…๋ฅ˜์˜ ํƒ€์ž… ๋‚ด์—์„œ ์š”์†Œ์˜ ์ˆœ์„œ๋ฅผ ์นด์šดํŠธ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, .myPath๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ฌถ๋“ , path๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ฌถ๋“  #logo ํ•˜์œ„์˜ 4๊ฐœ์˜ <path>๋งŒ์„ ์ƒ๊ฐํ•ด ๊ณ„์‚ฐํ•˜๋ฉด ๋œ๋‹ค.

 

 

stroke-dasharray, stroke-dashoffset

 

#logo path:nth-of-type(1) { stroke-dasharray: 50px; }

์œ„ ํƒœ๊ทธ๋ฅผ ์ ์šฉํ–ˆ์„ ๋•Œ๋Š” ์™ผ์ชฝ์˜ ๋ชจ์Šต๊ณผ ๊ฐ™๋‹ค.

์–ด๋–ค element์—๋“  ์ ์šฉ๊ฐ€๋Šฅํ•œ ์†์„ฑ์ด์ง€๋งŒ, ์‹ค์ œ๋กœ ํšจ๊ณผ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋Š” ํƒœ๊ทธ๋Š” ์•„๋ž˜ ์—ด ๋‘ ๊ฐœ๋กœ ์ œํ•œ์ ์ด๋‹ค.

 

<path>, <ellipse>, <line>, <polygon>, <rect>, <text>, <textPath>, <tref>, <tspan>, <altGlyph>, <circle>

 

dash๋ผ๋Š” ์ด๋ฆ„์ด ๋“ค์–ด๊ฐ€๋Š” ๊ทธ๋Œ€๋กœ, ์ ์„ ์„ ๋งŒ๋“ค์–ด์ฃผ๋Š” ์†์„ฑ์ด๋‹ค. ์ด ์†์„ฑ๊ณผ ๊ฐ™์ด stroke-dashoffset ์†์„ฑ์ด ์“ฐ์ด๋Š”๋ฐ, ์ด ์†์„ฑ์€ ์–ด๋””์—์„œ๋ถ€ํ„ฐ ์‹œ์ž‘ํ• ์ง€๋ฅผ ์ •ํ•ด์ค€๋‹ค.

 

 

Animation

์›ํ•˜๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜์€ ๊ธ€์ž๊ฐ€ ์ „ํ˜€ ์—†๋‹ค๊ฐ€ ์„œ์„œํžˆ path๊ฐ€ ๊ทธ๋ ค์ง€๋Š” ํ˜•ํƒœ๋กœ, ์ตœ์ข…์ ์œผ๋กœ๋Š” ์ „์ฒด๊ฐ€ ๋‹ค ๋ณด์ด๋„๋ก ํ•  ๊ฒƒ์ด๋‹ค. stroke-dasharray๊ฐ€ ํ•ด๋‹น ์š”์†Œ์˜ ์ „์ฒด ๊ธธ์ด์™€ ๋™์ผํ•˜๋‹ค๋ฉด, ์ ์„ ์€ ํ•˜๋‚˜๋„ ์—†๋Š” ์ƒํƒœ์ด๋‹ค. ๋งŒ์ผ offset๋„ ๋™์ผํ•˜๊ฒŒ ๊ฐ™์€ ๊ฐ’์ด๋ผ๋ฉด

์ด๋ ‡๊ฒŒ ์‚ฌ๋ผ์ ธ ์žˆ๋Š” ํ˜•ํƒœ๊ฐ€ ๋  ๊ฒƒ์ด๋‹ค. keyframe ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ํ†ตํ•ด stroke-dashoffset์„ 0์œผ๋กœ ์ฃผ๋„๋ก ํ•ด๋ณธ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  ๊ฐ path์—

animation: line-anime 5s ease-out forwards; ๋ฅผ ํ•œ ์ค„ ์ถ”๊ฐ€ํ•œ๋‹ค.

์ˆœ์„œ๋Œ€๋กœ ํ‚คํ”„๋ ˆ์ž„์˜ ์ด๋ฆ„, ์• ๋‹ˆ๋ฉ”์ด์…˜ ์†Œ์š” ์‹œ๊ฐ„, ์• ๋‹ˆ๋ฉ”์ด์…˜ timing function, animation-fill-mode ์ด๋‹ค. forwards๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ํ‚คํ”„๋ ˆ์ž„์— 100%์— ๋„๋‹ฌํ–ˆ์„ ๋•Œ ๋งˆ์ง€๋ง‰ ํ‚คํ”„๋ ˆ์ž„์„ ์œ ์ง€ํ•œ๋‹ค.

 

 

 

 

 

๋งˆ์ง€๋ง‰์œผ๋กœ path๋ฅผ ๊ทธ๋ฆฌ๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์ข…๋ฃŒ๋˜๋ฉด ์ „์ฒด ๊ธ€์ž๋ฅผ ํ•˜์–€์ƒ‰์œผ๋กœ ๊ทธ๋ฆฌ๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋„ฃ๊ณ  ์ข…๋ฃŒํ•˜๊ณ ์ž ํ•  ๋•Œ๋Š”, <svg> ํƒœ๊ทธ์™€ <mask> ํƒœ๊ทธ์— ๋™์‹œ์— ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ ์šฉํ•ด์•ผ ์ œ๋Œ€๋กœ ๋™์ž‘ํ–ˆ๋‹ค. #path-1-outside-1์€ <mask> ํƒœ๊ทธ์— ์ž๋™์œผ๋กœ ์„ค์ •๋˜์–ด ์žˆ๋˜ id ๊ฐ’์ด๋‹ค.

 

#logo,
#path-1-outside-1 {
  animation: fill-out 1s ease-out forwards 2s;
}

@keyframes fill-out {
  from {
    fill: transparent;
  }
  to {
    fill: white;
  }
}

 

ํ•œ๊ธ€์ผ ๊ฒฝ์šฐ

 

ํ•œ์ž์ผ ๊ฒฝ์šฐ

 

๊ฐœ์ธ์ ์œผ๋กœ๋Š” ์˜ˆ์‹œ๋กœ ์‚ฌ์šฉํ•œ ํ•œ์ž์˜ ๊ฒฝ์šฐ๊ฐ€ ๋” ์• ๋‹ˆ๋ฉ”์ด์…˜ ์›€์ง์ž„์ด ๋‹ค์–‘ํ•ด์„œ ์ ํ•ฉํ•ด ๋ณด์ธ๋‹ค.

๋‹ค์Œ์—๋Š” JavaScript๊ฐ€ ์•„๋‹Œ SCSS๋กœ๋งŒ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์ฐพ์•„๋‘๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

 

๋ˆŒ๋Ÿฌ์„œ ์ „์ฒด Code ๋ณด๊ธฐ ๐Ÿ‘€

'๐Ÿ‘ฉโ€๐Ÿ’ป > Web' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

SOP(Same-Origin-Policy), CORS(Cross-Origin-Resource-Sharing)  (0) 2021.05.10