브라우저에 그림을 그리는 방법 알아보기 (SVG vs Canvas)

Jake Seo·2020년 5월 7일
3

svg

목록 보기
1/1
post-thumbnail

브라우저에 그림을 그리는 방법 알아보기 (SVG vs Canvas)

브라우저에 그림을 넣으려면 어떤 방법이 있을까? 간단하게는 3가지 방법이 있다고 생각한다.

  1. 그림을 그림판이나 포토샵에서 그려서 첨부하기
  2. SVG를 이용하기
  3. Canvas를 이용하기

그렇다면 상황에 맞는 선택지는?

  • 제약 없이 내가 만든 이미지를 넣고 싶을 때
    • 직접 첨부
  • 해상도가 깨지지 않는 평면의 컬러 아이콘을 만들고 싶을 때
    • SVG
  • 사용자와 상호작용하는 콘솔같은 게임을 만들 때
    • Canvas

SVG의 특성

  1. 이미지에서 자주 발생하는 현상인 해상도에 따라 깨지는 현상이 없음
  2. 벡터 아트(주로 조그만 이미지)를 구현할 때 적합
  3. 아이콘 등을 표기할 때 적합
  4. 다소 선언적(declarative)이다.
    • 컴퓨터에게 어디에 어떻게 그릴지만 이야기해주면 된다.

아래와 같은 테스트 코드를 작성하면

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <svg viewBox="0 0 50 50">
      <circle cx="10" cy="10" r="1" />
    </svg>
  </body>
</html>

아래와 같이 벡터로 만든 점이 브라우저에 표기됨

아래처럼 해상도를 마구 줄이거나 늘려도 벡터 이미지는 깨지지 않고 자기의 자리를 찾아간다

캔버스의 특성

  1. 캔버스는 자바스크립트 드로잉 API이다
  2. 다소 명령적(imperative)이다
    • 컴퓨터가 어떻게 그려나갈지 컴퓨터의 입장에서 명령해주어야 한다.

다음은 초록색 공을 그리는 코드이다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <canvas id="myCanvas" width="578" height="200"></canvas>
    <script>
      var canvas = document.getElementById('myCanvas');
      var context = canvas.getContext('2d');
      var centerX = canvas.width / 2;
      var centerY = canvas.height / 2;
      var radius = 70;

      context.beginPath();
      context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
      context.fillStyle = 'green';
      context.fill();
    </script>
  </body>
</html>

결과는 다음과 같다.

DOM에 있는 SVG

clickmouseDown과 같은 DOM 이벤트와 친숙하다면, SVG의 circle 태그를 div 태그처럼 사용할 수 있습니다.

아래는 클릭하면 빨간색으로 변하는 공을 그린 것입니다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <svg viewBox="0 0 100 100">
      <circle cx="20" cy="20" r="10" />

      <script>
        document.querySelector('circle').addEventListener('click', e => { e.target.style.fill =
        "red"; });
      </script>
    </svg>
  </body>
</html>

결과는 다음과 같습니다.

SVG의 접근성

canvas는 text alternative를 사용할 수 있다.

아래와 같은 코드를 적용하면 된다.

<canvas aria-label="Hello ARIA World" role="img"></canvas>

SVG도 같은 것을 할 수 있다. 하지만 SVG에서는 SVG의 메인 엘리먼트를 접근하고 그에 대한 서브 엘리먼트를 접근하는 방식으로 해나가야 한다.

SVG는 CSS로 스타일을 먹일 수 있다

아래와 같이 코드를 작성하면, 일반적으로 태그에 CSS를 먹이는 것처럼 SVG 내부 엘리먼트에 CSS를 먹일 수 있다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <svg viewBox="0 0 100 100">
      <circle cx="20" cy="20" r="5" />

      <style>
        circle {
          fill: blue;
        }
      </style>
    </svg>
  </body>
</html>

위 소스를 실행시키면 파란색 공이 나온다.

그리고 hover라던지, 애니메이션 등과 같은 예제도 가능하다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <svg viewBox="0 0 100 100">
      <circle cx="50" cy="50" r="20" />

      <style>
        circle:hover {
          fill: blue;
          animation: pulse 2s alternate infinite;
        }
        @keyframes pulse {
          100% {
            r: 30;
          }
        }
      </style>

      <script>
        document.querySelector('circle').addEventListener('click', e => { e.target.style.fill =
        "red"; });
      </script>
    </svg>
  </body>
</html>

좀 더 많은 예제는 여기에서 볼 수 있다. 앞의 링크에는 신기한 예제들이 많다.

SVG와 캔버스는 완전히 배타적이지 않다

https://codepen.io/osublake/pen/WzbKLQ

위 링크의 예제에서는 같은 기능을 하는 애니메이션을 CanvasSVG로 각각 구현한다.

SVG로 구현할 수 있는 건 Canvas로도 구현 가능하다.

Canvas와 SVG 비교 표 (Ruth John's comparison)

Sarah Drasner's comparison

Shirley Wu's comparison

결론

기본적인 선택으로는 SVG가 옳다.

  • 쉬운 접근성
  • 작은 러닝커브
  • 애니메이션을 구현하기도 쉬움
  • 기본적 DOM구조

Canvas는 추가적인 옵션

  • 콘솔같은 게임을 구현할 때
  • 자바스크립트에 익숙한 전문가가 사용할 때

한줄 평

  • SVG로 안되는 것이 있을 때, Canvas를 사용하라

참고자료

https://css-tricks.com/when-to-use-svg-vs-when-to-use-canvas/

profile
풀스택 웹개발자로 일하고 있는 Jake Seo입니다. 주로 Jake Seo라는 닉네임을 많이 씁니다. 프론트엔드: Javascript, React 백엔드: Spring Framework에 관심이 있습니다.

0개의 댓글