본문 바로가기
Programming

SVG란 무엇인가? CSS 적용하기

by 개발자 염상진 2023. 1. 3.

 

 

SVG란 무엇인가?

 

SVG(Scalable Vector Graphics) 란 2차원 벡터 그래픽을 위한 XML로 구성된 벡터 그래픽 형식의 파일을 의미합니다. SVG 기술 덕분에 우리는 화면 확대를 아무리 해도 깨지지 않는 이미지를 얻을 수 있게 됩니다. 어떻게 이게 가능하냐구요? 

 

 

 

다음 그림을 한번 보시면 두 그림의 차이점이 분명하게 보이실 겁니다.

 

 

왼쪽을 보시면 그래픽이 정상적으로 출력됩니다. 하지만 오른쪽 빨간색 그림은 그림이 깨져서 보이게 됩니다. SVG를 이해하기 위해서 먼저 아셔야 하는 개념이 바로 벡터와 비트맵입니다.

 

벡터와 비트맵

 

비트맵은 그림의 위치를 정확하게 기억하고 있습니다. 따라서 그림이 확대가 되게 되면 해당 위치의 색상을 정확하게 기억하고 있기 때문에 깨져서 보이는 현상이 발생하게 됩니다. 

출처 :https://business.oregonstate.edu/

 

오른쪽 그림을 보시면 비트맵의 경우 여러개의 픽셀로 구성된 그림을 표 위에 표시하고 있습니다. 정확한 좌표값과 색상값을 가지고 있기 때문에 웬만큼 축소해서 보지 않는 이상 조금 어색한 이미지가 표현되어 버립니다.

 

 

반면 벡터의 경우 수학적으로 계산된 공식에 따라 라인으로 그림을 그리고 있습니다. 왼쪽을 보시면 아무리 확대를 하더라도 사전에 계산된 값에 따라서 그림을 그리기 때문에 그림이 깨지지 않게 보입니다. 훨씬 자연스럽죠.

 

  • JPEG, PNG, GIF, BMP, TIF 등의 확장자를 가진 이미지들은 비트맵을 사용합니다.
  • EPS, AI, TGA 등의 확장자를 가진 illustrate, flash 파일들은 벡터를 사용합니다.

 

SVG 만드는 방법

 

자 이제 비트맵과 벡터의 차이에 대해 알아보았으니, SVG를 실제로 그려보는 작업을 해봅시다.

먼저 아래 사이트에 접속하셔서 간단한 그림을 그려줍니다.

https://app.diagrams.net/

 

 

저도 아래와 같은 멋진 그림을 그렸습니다. 1분도 안걸렸습니다.

 

그리신 후에 상단 메뉴에서 파일 > 다른 이름으로 저장을 클릭합니다.

 

여러가지 이미지 포맷을 지원해 주고 있습니다. 우리는 svg를 선택합니다.

 

다운로드가 완료되면 이미지를 vscode에서 실행해봅니다. SVG 파일은 이미지를 설명하는 여러줄의 코드로 구성되어 있습니다. path 태그의 속성값은 이미지의 좌표를 의미하는 것으로 보입니다. 

<?xml version="1.0" encoding="UTF-8"?>
<!-- Do not edit this file with editors other than diagrams.net -->
<!-- <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"
    width="285px" height="391px" viewBox="-0.5 -0.5 285 391"
    content="&lt;mxfile host=&quot;app.diagrams.net&quot; modified=&quot;2023-01-03T00:45:57.919Z&quot; agent=&quot;5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36&quot; version=&quot;20.8.0&quot; etag=&quot;nJe40R1DRxGUQUWJfasr&quot; type=&quot;device&quot;&gt;&lt;diagram id=&quot;xRWBeOlpOg0oTK3nXwj9&quot; name=&quot;페이지-1&quot;&gt;xVZNk9owDP01ObaTLwIcF5bdznR7ojOlRxMriVsnCo4DYX99HaKQZLLLbFsYLmA9WbKlp+eJ5S3T6lmxPPmGHKTl2ryyvEfLdadz3/zWwJEAe9oAsRK8gZwOWItXINAmtBQcisFGjSi1yIdgiFkGoR5gTCk8DLdFKIen5iyGEbAOmRyjPwTXSYPO3GmHfwERJ+3JTjBvPClrN1MlRcI4HnqQt7K8pULUzSqtliDr3rV9aeKe3vGeL6Yg0x8J2MQP4WuGDxOdf013kbP57uw+ETuFPrYFAzf1k4lKJxhjxuSqQxcKy4xDndU2VrfnBTE3oGPAX6D1kchkpUYDJTqV5A1LtT/F10ZzgfrUd+siqMBShXChmHY+mIpBX9jnnrtvphYwBa2OJk6BZFrsh/dgND/xeV/XYrOgLv9FxynvnsmSTrLcQJrrLiI0BZsRZVRksCvr2Vi8lKHgzHiWmBVoKDh7zCqu/9emZN2mMbdqMjW+McFSGvHURB4SoWGdN+cdjHyHNLEibxQViaqmaxEJKZcoUZ0SeXwCM+4bvNAKf0PPM3O3XhBQSe0wtYWD0lBd5nrMDQWcnwV6TRyf7ENPmwQlPVm22NXZnPyDfgbj/99igkroTR3+eULWz57nsaLMJ+NIxhU1535Qc949NeeONLfWkDtj7q4ljSiCIAzfkgafzre2TdJ4YqmQNSkjid9AOvOhdM72vaTjjUh5RiZv+FwxmEVvchKEM9hGd+DEd/wBJ/7kZpwYs/vUOPl632ve6g8=&lt;/diagram&gt;&lt;/mxfile&gt;">
    <defs />
    <g>
        <path d="M 40 80 Q 40 115 80 115 Q 120 115 120 143.63" fill="none" stroke="rgb(0, 0, 0)"
            stroke-miterlimit="10" pointer-events="stroke" />
        <path d="M 120 148.88 L 116.5 141.88 L 120 143.63 L 123.5 141.88 Z" fill="rgb(0, 0, 0)"
            stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" />
        <ellipse cx="40" cy="40" rx="40" ry="40" fill="#d5e8d4" stroke="#82b366"
            pointer-events="all" />
        <g transform="translate(-0.5 -0.5)">
            <switch>
                <foreignObject pointer-events="none" width="100%" height="100%"
                    requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"
                    style="overflow: visible; text-align: left;">
                    <div xmlns="http://www.w3.org/1999/xhtml"
                        style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 1px;">
                        <div data-drawio-colors="color: rgb(0, 0, 0); "
                            style="box-sizing: border-box; font-size: 0px; text-align: center;">
                            <div
                                style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">
                                <font face="Lucida Console">Start</font>
                            </div>
                        </div>
                    </div>
                </foreignObject>
                <text x="40" y="44" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px"
                    text-anchor="middle" font-weight="bold">Start</text>
            </switch>
        </g>
        <path d="M 120 230 Q 120 270 182 270 Q 244 270 244 303.63" fill="none" stroke="rgb(0, 0, 0)"
            stroke-miterlimit="10" pointer-events="stroke" />
        <path d="M 244 308.88 L 240.5 301.88 L 244 303.63 L 247.5 301.88 Z" fill="rgb(0, 0, 0)"
            stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" />
        <ellipse cx="120" cy="190" rx="40" ry="40" fill="#ffe6cc" stroke="#d79b00"
            pointer-events="all" />
        <g transform="translate(-0.5 -0.5)">
            <switch>
                <foreignObject pointer-events="none" width="100%" height="100%"
                    requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"
                    style="overflow: visible; text-align: left;">
                    <div xmlns="http://www.w3.org/1999/xhtml"
                        style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 190px; margin-left: 81px;">
                        <div data-drawio-colors="color: rgb(0, 0, 0); "
                            style="box-sizing: border-box; font-size: 0px; text-align: center;">
                            <div
                                style="display: inline-block; font-size: 12px; font-family: &quot;Lucida Console&quot;; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">
                                Step1</div>
                        </div>
                    </div>
                </foreignObject>
                <text x="120" y="194" fill="rgb(0, 0, 0)" font-family="Lucida Console"
                    font-size="12px" text-anchor="middle" font-weight="bold">Step1</text>
            </switch>
        </g>
        <ellipse cx="244" cy="350" rx="40" ry="40" fill="#dae8fc" stroke="#6c8ebf"
            pointer-events="all" />
        <g transform="translate(-0.5 -0.5)">
            <switch>
                <foreignObject pointer-events="none" width="100%" height="100%"
                    requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"
                    style="overflow: visible; text-align: left;">
                    <div xmlns="http://www.w3.org/1999/xhtml"
                        style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 350px; margin-left: 205px;">
                        <div data-drawio-colors="color: rgb(0, 0, 0); "
                            style="box-sizing: border-box; font-size: 0px; text-align: center;">
                            <div
                                style="display: inline-block; font-size: 12px; font-family: &quot;Lucida Console&quot;; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">
                                Goal</div>
                        </div>
                    </div>
                </foreignObject>
                <text x="244" y="354" fill="rgb(0, 0, 0)" font-family="Lucida Console"
                    font-size="12px" text-anchor="middle" font-weight="bold">Goal</text>
            </switch>
        </g>
    </g>
    <switch>
        <g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" />
        <a transform="translate(0,-5)"
            xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank">
            <text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot
                display</text>
        </a>
    </switch>
</svg>

 

HTML 파일에 SVG 파일을 삽입합니다.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

    <h1>Sample Image</h1>
    <div class="mysvg">
        <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="285px"
            height="391px" viewBox="-0.5 -0.5 285 391"
            content="&lt;mxfile host=&quot;app.diagrams.net&quot; modified=&quot;2023-01-03T00:45:57.919Z&quot; agent=&quot;5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36&quot; version=&quot;20.8.0&quot; etag=&quot;nJe40R1DRxGUQUWJfasr&quot; type=&quot;device&quot;&gt;&lt;diagram id=&quot;xRWBeOlpOg0oTK3nXwj9&quot; name=&quot;페이지-1&quot;&gt;xVZNk9owDP01ObaTLwIcF5bdznR7ojOlRxMriVsnCo4DYX99HaKQZLLLbFsYLmA9WbKlp+eJ5S3T6lmxPPmGHKTl2ryyvEfLdadz3/zWwJEAe9oAsRK8gZwOWItXINAmtBQcisFGjSi1yIdgiFkGoR5gTCk8DLdFKIen5iyGEbAOmRyjPwTXSYPO3GmHfwERJ+3JTjBvPClrN1MlRcI4HnqQt7K8pULUzSqtliDr3rV9aeKe3vGeL6Yg0x8J2MQP4WuGDxOdf013kbP57uw+ETuFPrYFAzf1k4lKJxhjxuSqQxcKy4xDndU2VrfnBTE3oGPAX6D1kchkpUYDJTqV5A1LtT/F10ZzgfrUd+siqMBShXChmHY+mIpBX9jnnrtvphYwBa2OJk6BZFrsh/dgND/xeV/XYrOgLv9FxynvnsmSTrLcQJrrLiI0BZsRZVRksCvr2Vi8lKHgzHiWmBVoKDh7zCqu/9emZN2mMbdqMjW+McFSGvHURB4SoWGdN+cdjHyHNLEibxQViaqmaxEJKZcoUZ0SeXwCM+4bvNAKf0PPM3O3XhBQSe0wtYWD0lBd5nrMDQWcnwV6TRyf7ENPmwQlPVm22NXZnPyDfgbj/99igkroTR3+eULWz57nsaLMJ+NIxhU1535Qc949NeeONLfWkDtj7q4ljSiCIAzfkgafzre2TdJ4YqmQNSkjid9AOvOhdM72vaTjjUh5RiZv+FwxmEVvchKEM9hGd+DEd/wBJ/7kZpwYs/vUOPl632ve6g8=&lt;/diagram&gt;&lt;/mxfile&gt;">
            <defs />
            <g>

                <path d="M 40 80 Q 40 115 80 115 Q 120 115 120 143.63" fill="none" stroke="rgb(0, 0, 0)"
                    stroke-miterlimit="10" pointer-events="stroke" />

                
                    <path d="M 120 148.88 L 116.5 141.88 L 120 143.63 L 123.5 141.88 Z" fill="rgb(0, 0, 0)"
                        stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" />
                
                
                    <ellipse cx="40" cy="40" rx="40" ry="40" fill="#d5e8d4" stroke="#82b366"
                        pointer-events="all" />
                
                <g transform="translate(-0.5 -0.5)">
                    <switch>
                        <foreignObject pointer-events="none" width="100%" height="100%"
                            requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"
                            style="overflow: visible; text-align: left;">
                            <div xmlns="http://www.w3.org/1999/xhtml"
                                style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 1px;">
                                <div data-drawio-colors="color: rgb(0, 0, 0); "
                                    style="box-sizing: border-box; font-size: 0px; text-align: center;">
                                    <div
                                        style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">
                                        <font face="Lucida Console">Start</font>
                                    </div>
                                </div>
                            </div>
                        </foreignObject>
                        <text x="40" y="44" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px"
                            text-anchor="middle" font-weight="bold">Start</text>
                    </switch>
                </g>
                <path d="M 120 230 Q 120 270 182 270 Q 244 270 244 303.63" fill="none" stroke="rgb(0, 0, 0)"
                    stroke-miterlimit="10" pointer-events="stroke" />
                <path d="M 244 308.88 L 240.5 301.88 L 244 303.63 L 247.5 301.88 Z" fill="rgb(0, 0, 0)"
                    stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" />
                <ellipse cx="120" cy="190" rx="40" ry="40" fill="#ffe6cc" stroke="#d79b00" pointer-events="all" />
                <g transform="translate(-0.5 -0.5)">
                    <switch>
                        <foreignObject pointer-events="none" width="100%" height="100%"
                            requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"
                            style="overflow: visible; text-align: left;">
                            <div xmlns="http://www.w3.org/1999/xhtml"
                                style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 190px; margin-left: 81px;">
                                <div data-drawio-colors="color: rgb(0, 0, 0); "
                                    style="box-sizing: border-box; font-size: 0px; text-align: center;">
                                    <div
                                        style="display: inline-block; font-size: 12px; font-family: &quot;Lucida Console&quot;; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">
                                        Step1</div>
                                </div>
                            </div>
                        </foreignObject>
                        <text x="120" y="194" fill="rgb(0, 0, 0)" font-family="Lucida Console" font-size="12px"
                            text-anchor="middle" font-weight="bold">Step1</text>
                    </switch>
                </g>
                <ellipse cx="244" cy="350" rx="40" ry="40" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" />
                <g transform="translate(-0.5 -0.5)">
                    <switch>
                        <foreignObject pointer-events="none" width="100%" height="100%"
                            requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"
                            style="overflow: visible; text-align: left;">
                            <div xmlns="http://www.w3.org/1999/xhtml"
                                style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 350px; margin-left: 205px;">
                                <div data-drawio-colors="color: rgb(0, 0, 0); "
                                    style="box-sizing: border-box; font-size: 0px; text-align: center;">
                                    <div
                                        style="display: inline-block; font-size: 12px; font-family: &quot;Lucida Console&quot;; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">
                                        Goal</div>
                                </div>
                            </div>
                        </foreignObject>
                        <text x="244" y="354" fill="rgb(0, 0, 0)" font-family="Lucida Console" font-size="12px"
                            text-anchor="middle" font-weight="bold">Goal</text>
                    </switch>
                </g>
            </g>
            <switch>
                <g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" />
                <a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems"
                    target="_blank">
                    <text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot
                        display</text>
                </a>
            </switch>
        </svg>
    </div>
</body>

</html>

 

이미지가 짜잔 하고 등장했습니다. 

 

 

 

SVG에 효과주기

 

SVG 는 수학적으로 계산된 값들을 이어 놓은 파일 형태이므로 특정 값을 가지고 사용자가 임의 행동을 지정할 수 있습니다. 

SVG 파일이 떠있는 웹 페이지에서 Ctrl+Shift+C 를 누르시면 개발자 화면이 나옵니다. 여기서 우측 상단의 마우스를 클릭하고 우리가 선탠하고자 하는 원을 클릭합니다.

firstcircle의 경우 ellipse 태그에 속해있습니다. 

이제 이 태그를 a 태그로 감싸주고 아래 코드를 추가해줍니다.

<a id="firstcircle" xlink:title="first-step" xlink:href="https://www.rapollon.com">
                    <ellipse cx="40" cy="40" rx="40" ry="40" fill="#d5e8d4" stroke="#82b366"
                        pointer-events="all" />
                </a>

 

이제 first 원을 클릭하면 특정 링크로 이동하게 됩니다.

 

 

Hover 효과 주기

다음으로는 첫번째 원에 Hover 효과를 삽입합니다.

head 태그 하위에 style 태그를 넣고 아래 코드를 넣습니다.

<style>
        #firstcircle :hover {
            fill: rgb(238, 29, 29);
        }
    </style>

 

이제 Start 원에 마우스를 올리면 이미지에 동적인 효과가 적용되어 빨간색으로 색이 변경됩니다. 

 

 

 

Reference

https://jenkov.com/tutorials/svg

SVG 작품들

opentutirals SVG

 

 

 

'Programming' 카테고리의 다른 글

Node.js 크롤링 하는 방법  (0) 2023.01.05
Web이란 무엇인가?  (0) 2023.01.03
2022년 회고  (0) 2023.01.02
CI/CD #4 배포 구성하기 AWS EC2 [최종]  (0) 2022.12.29
CI/CD #3 배포 구성하기 Github Actions  (0) 2022.12.29

댓글