SVG 애니메이션 만들기 (React/Next.js)

Joey Hong·2020년 7월 22일
6

React/Next.js

목록 보기
2/3

SVG 애니메이션 (React, Next.js)

SVG란?

  • SVG는 Scalable Vector Graphics 로 2차원의 벡터 이미지를 표현하는 언어입니다.

  • 마크업 언어를 기반으로 하고 있는데 그 중에서도 XML 의 문법을 이용하고 있습니다.

  • 벡터 기반으로 이미지를 표현하기 때문에 이미지의 해상도나 크기가 바뀌어도 원본 그대로의 퀄리티를 보장해준다는 장점이 있습니다.

  • 컴퓨터 그래픽은 크게 비트맵과 벡터로 구분되며 SVG는 벡터 그래픽에 속합니다.

Bitmap vs. Vector

1. Bitmap (Raster)

  • Bitmap은 비트의 지도 (map of bits)라는 의미로 각 픽셀에 저장된 비트 정보들의 집합입니다.
    • 픽셀들의 개수 등이 디스플레이의 해상도를 결정짓습니다.
    • 즉, 1920 x 1080 해상도의 디스플레이는 가로 1920개 세로 1080개의 픽셀들을 가집니다.
  • 최종적으로 렌더링 된 상태라 편집이 어렵고 수정한다해도 이미지 퀄리티를 보장하기 어렵습니다.
  • 이미지를 확대/축소할 경우 이미지에 손상이 가 계단현상이 발생합니다.
  • 벡터 포맷에 비해 복잡한 이미지를 더 빠르고 효율적으로 보여줄 수 있습니다.

2. Vector

  • Vector 방식은 이미지들이 수학적 공식으로 이루어져 있습니다.
    • 두 개의 좌표가 있으면 그 점들을 연결해 하나의 선을 만듭니다.
    • 선을 세 개 이상 조합해 면을 만들 수 있습니다.
    • 각 선은 두께, 색상, 곡률을 각 면은 색상을 가질 수 있습니다.
  • 벡터 포맷의 파일이 유지되는 한 언제든지 수정이 가능하며 원하는 해상도로 내보내기가 가능합니다.
  • 복잡한 도형은 처리시간이 길어질 수 있습니다.

SVG 애니메이션 만들어보기

1. SVG 만들기

  • Adobe Illustrator, Photoshop 등을 이용해 벡터 이미지를 만듭니다.
    • Figma는 위 툴들의 핵심 기능을 갖추고 있으면서도 가벼운 무료 온라인 툴입니다.
    • Figma로 손쉽게 SVG를 얻을 수 있어 Figma로 그래픽을 만들었습니다.
  • 같은 애니메이션을 적용할 이미지들은 하나의 그룹으로 묶어줍니다.
    • 각 뱃지에 다른 애니메이션을 적용하기 위해 뱃지별로 그룹을 생성했습니다.

  • 최상위 그룹을 클릭한 뒤 "include id Attribute"를 체크해 export 해줍니다.

  • Export한 badge animation을 에디터에서 열어보면 코드를 확인할 수 있습니다.

2. SVG 사용하기

  • React에서 svg를 사용하기 위해서는 svg 언어를 jsx 스타일로 바꿔야합니다.

    • :[소문자]-[소문자]를 각각 :[대문자]-[대문자]로 바꾸는 등의 규칙이 있습니다.

    • SVG를 jsx로 바꿔주는 사이트는 두 가지를 사용해봤습니다. SVGR vs. svg2jsx

    • svg2jsx는 overlay, multiply등의 기능을 구현해주지만 사이트가 다운되어있을 때도 있어 둘 다 사용해보는 것을 권장합니다.

    • SVGR 사이트의 좌측에 svg 코드를 붙여넣으면 우측에서 jsx스타일로 변형 후 리액트 함수까지 만들어준 코드를 반환합니다.

  • html에 svg를 바로 넣으면 가독성이 떨어지기 때문에 jsx로 변환된 badge animation코드를 컴포넌트에 넣습니다.

    • Animation.js 컴포넌트를 만들고 return에 svg 코드를 그대로 복사해서 넣습니다.
    function Animation() {
        return (
            <svg>
        );
    }
  • 혹시 이미지에 clipping mask나 overlay 등의 기능을 활용한다면 svg가 인식하지 못 할 수 있어 벡터를 래스터화하거나 직접 코드를 수정하는 등의 작업이 필요합니다. 변환 전의 svg코드를 SVGOMG 사이트에서 기능 적용 후, 그 코드를 jsx로 변환하면 됩니다.
  • 일반 컴포넌트처럼 index.js에서 불러옵니다.


3. ViewBox로 사이즈 조정하기

  • viewBox는 아래와 같이 네 개의 숫자를 지정해 사용합니다.
	viewBox = [min-x] [min-y] [width] [height]
  • 마지막 두 숫자는 zooming에 관한 것으로 실제 이미지의 얼마만큼을 보여줄지를 결정합니다.

  • 가로 세로 100px의 원이 있습니다. 이 원을 모두 보여주려면 마지막 두 숫자를 최소 700으로 지정해줍니다.

	<svg viewbox="0 0 100 100">

  • 원의 크기를 50px로 줄이고 싶다면 어떻게 하면 될까요?
	<svg viewBox="0 0 50 50">
  • 마지막 두 숫자를 50으로 지정해준다면 세로의 반, 가로의 반만 보여 원의 1/4이 보여지게 됩니다.

  • 사로 세로 50px의 원을 디스플레이하고싶은 경우 viewBox의 마지막 두 숫자의 원크기로 지정하고 따로 width와 height를 지정해주면 됩니다.
	<svg width="50" height="50" viewBox="0 0 100 100">

4. SVG className 지정하기

  • 애니메이션을 적용하기위해서는 뱃지별로 className을 지정해줘야하기때문에 Animation.js의 css 모듈 파일을 만들고 import 해줍니다.
	import styles from './Animation.module.css';
  • 복사해온 코드에는 className이나 id가 사라져있는 상태라 어디부터 어디까지가 원하는 이미지들의 그룹인지 알 수 없습니다. 따라서 figma에서 export한 badge animation 파일을 다시 열어봅니다.

  • 그룹명이 있는 badge animation를 참고해 그룹명이 없는 Animation.js에서 뱃지별로 className을 넣어줍니다.

  • 예를 들어 aptitude badge className을 넣어보겠습니다.

    • aptitude badge는 figma 작업 당시 가장 위에 있던 그룹레이어라 badge animation 코드의 하단에서 찾아볼 수 있습니다. (순서가 반대로 출력)

    • aptitude badge 그룹 내의 숫자를 아무거나 Animation.js에서 검색해봤습니다
   d="M113 144.5H190V187.5H113V144.5Z
  • 해당 코드를 포함하고 있는 그룹을 찾아 뱃지 이름을 지정해줍니다.

  • 같은 방식으로 codingtest badge, interview badge, tryout badge className도 지정해줍니다.

5. Animation 적용하기

  • keyframes를 이용해 애니메이션을 만들어줍니다.

    • 애니메이션 이름은 aptitude

    • 작동방식은 Y축으로 30px 움직이는 것입니다.

    • 0%, 50%, 100%는 각각 애니메이션이 시작했을 때, 반 진행되었을 때, 끝났을 때입니다.

    @keyframes aptitude {
        0% {
            transform: translateY(0px);
        }
        50% {
            transform: translateY(30px);
        }
        100% {
            transform: translateY(0px);
        }
    }
  • aptitude_badge에 애니메이션을 지정하고 옵션을 설정해줍니다.
    .aptitude_badge {
    animation: aptitude 2.5s infinite;
	}
  • 첫번째 뱃지 aptitude badge가 위아래로 움직이는 것을 확인할 수 있습니다.
  • 애니메이션 지정 규칙
    .[className] {
    animation: [name] [duration] [timing function] [iteration] [direction];
    }
profile
개발기록

1개의 댓글

comment-user-thumbnail
2020년 7월 25일

너무 대단하세요...

답글 달기