랜덤 숫자에 따라 SVG 출력

고은정·2021년 3월 22일
1

TIL

목록 보기
1/31
post-thumbnail

4개의 SVG 준비!

네개의 컵에 단계가 다른 물을 준비한다.
1단계부터 4단계까지 있으며, 단계가 올라갈수록 컵에 물이 차오르고, 물의 색은 위험을 나타내는 붉은색을 띈다.
가장 높은 단계인 4단계에서는 물이 넘치면서 살짝 튀기는 모습도 구현했다.(어색하지만,,😢)

준비한 물은 다음과 같다.

랜덤한 수 출력

자바스크립트로 랜덤한 수를 생성해서 출력한다.

  • 1 ~10 : 1단계
  • 11 ~ 20 : 2단계
  • 21 ~ 30 : 3단계
  • 31 ~ 40 : 4단계

위 숫자에 따른 단계에 일치하도록 랜덤한 숫자와 물컵을 출력한다.

구현이유

cpu, mem, disk 용량이나 프로그램의 사용시간에 따른 과부화 정도 등 동적인 데이터들을 구현한 물컵을 이용해서 직관적이고 귀엽게 표현하기 위해 구현했다.

현재는 단순하게 랜덤값을 한개만 가지고 오기 때문에 SVG를 랜덤으로 출력하는 것에 대한 브라우저의 활성 정도를 확실하게 확인하기가 어렵지만, 더 많은 동적인 데이터를 표현한다면 통계가 필요할 것 같다.

결과

코드 - html

<!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>eunjeong</title>
    <link rel="stylesheet" href="./style.css" />
    <!-- svg.js -->
    <script src="https://cdn.jsdelivr.net/npm/@svgdotjs/svg.js@3.0/dist/svg.min.js"></script>
</head>

<body style="padding: 20px;">
    <h1>랜덤 숫자별로 다른 물컵을 가져오기</h1>

    <p>Random : <span id="random"></span></p>

    <div id="cupArea"></div>


    <div class="container">
        <p>1단계</p>
        <div id="one">
            <svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="200"
                height="200">

                <path d="M42,130 C 50 120, 60 140, 80 120 S 110 140, 130 120 L122, 150 45, 150z" stroke="#C8F4F9"
                    fill="#C8F4F9" stroke-width="3" stroke-linecap="round">
                    <animate repeatCount="indefinite" fill="#C8F4F9" attributeName="d" dur="4s" attributeType="XML"
                        values="
                        M42,110 C 50 130, 60 110, 80 130 S 110 120, 130 110 L122, 150 45, 150z;
                        M42,130 C 50 120, 60 140, 80 120 S 110 140, 130 120 L122, 150 45, 150z;
                        M42,120 C 50 130, 60 110, 80 120 S 110 120, 130 120 L122, 150 45, 150z;
                        M42,110 C 50 120, 60 140, 80 120 S 110 140, 130 120 L122, 150 45, 150z;
                        M42,110 C 50 130, 60 110, 80 130 S 110 120, 130 110 L122, 150 45, 150z;

                    
                    " />
                </path>

                <polygon points="20,5 150,5 125,150 45,150 " fill="none" stroke="#000" stroke-width="3" />
            </svg>
        </div>
    </div>
    <div class="container">
        <p>2단계</p>
        <div id="two">
            <svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="200"
                height="200">
                <path d="M38,110 C 50 100, 65 80, 80 100 S 95 80, 110 100, 130 80, 133 100 L125, 150 45, 150z"
                    stroke="#47D3CE" fill="#47D3CE" stroke-width="3" stroke-linecap="round">
                    <animate repeatCount="indefinite" fill="#47D3CE" attributeName="d" dur="3s" attributeType="XML"
                        values="
                    M38,100 C 50 110, 65 100, 80 90 S 95 80, 110 80, 130 100, 133 100 L125, 150 45, 150z;
                    M33,80 C 50 100, 65 80, 80 80 S 95 110, 110 120, 130 80, 133 110 L125, 150 45, 150z;
                    M38,110 C 50 70, 65 60, 80 70 S 95 90, 110 80, 130 70, 133 80 L125, 150 45, 150z;
                    M33,80 C 50 80, 65 80, 80 100 S 95 110, 110 80, 130 110, 130 100 L125, 150 45, 150z;
                    M38,100 C 50 90, 65 110, 80 95 S 95 80, 110 80, 130 90, 130 115 L125, 150 45, 150z;
                    
                    
                    " />
                </path>

                <polygon points="20,5 150,5 125,150 45,150" fill="none" stroke="#000" stroke-width="3" />
            </svg>
        </div>
    </div>
    <div class="container">
        <p>3단계</p>
        <div id="three">
            <svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="200"
                height="200">
                <path d="M38,90 C 60 80, 65 50, 80 80 S 95 80, 110 100, 130 80, 135 90 L125, 150 45, 150z"
                    stroke="#FCA4A2" fill="#FCA4A2" stroke-width="3" stroke-linecap="round">
                    <animate repeatCount="indefinite" fill="#FCA4A2" attributeName="d" dur="2s" attributeType="XML"
                        values="
                        M35,100 C 60 70, 65 90, 80 80 S 95 65, 110 80, 130 80, 135 90 L125, 150 45, 150z;
                        M33,65 C 60 60, 65 70, 80 65 S 95 75, 110 83, 130 60, 137 70 L125, 150 45, 150z;
                        M35,85 C 60 90, 65 80, 80 90 S 95 60, 110 90, 130 70, 135 80 L125, 150 45, 150z;
                        M35,80 C 60 70, 65 60, 80 70 S 95 70, 110 95, 130 90, 137 70 L125, 150 45, 150z;
                        M35,90 C 60 70, 65 90, 80 80 S 95 65, 110 80, 130 80, 135 90 L125, 150 45, 150z;
                        
                        

                    
                    " />
                </path>
                <polygon points="20,5 150,5 125,150 45,150" fill="none" stroke="#000" stroke-width="3" />
            </svg>
        </div>
    </div>
    <div class="container">
        <p>4단계</p>
        <div id="four">
            <svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="200"
                height="200">
                <path d="M24,30 C 50 20, 65 10, 80 20 S 95 10, 110 20, 130 30, 147 10 L125, 150 45, 150z"
                    stroke="#E78484" fill="#E78484" stroke-width="3" stroke-linecap="round">
                    <animate repeatCount="indefinite" fill="#E78484" attributeName="d" dur="2s" attributeType="XML"
                        values="
                        M24,20 C 50 40, 65 30, 80 13 S 95 25, 110 15, 130 40, 147 15 L125, 150 45, 150z;
                        M26,40 C 50 20, 65 10, 80 20 S 95 30, 110 20, 130 13, 147 25 L125, 150 45, 150z;
                        M24,10 C 50 13, 65 25, 80 15 S 95 10, 110 30, 130 20, 147 15 L125, 150 45, 150z;
                        M26,35 C 50 10, 65 35, 80 30 S 95 20, 110 13, 130 25, 147 6 L125, 150 45, 150z;
                        M24,15 C 50 15, 65 10, 80 25 S 95 15, 110 20, 130 30, 147 25 L125, 150 45, 150z;

                    
                    " />
                </path>

                <!-- 물튀기기 같은 시간의 애니메이션으로 안보이게 처리해야하나,,? -->
                <path d="M155 10 C 160 5, 170 25, 165,30z" fill="#E78484">
                    <animate repeatCount="indefinite" fill="#E78484" attributeName="d" dur="2s" attributeType="XML"
                        values="
                        M0,0;
                        M0,0;
                        M0,0;
                    M155 10 C 158 5, 160 20 160 17z;
                    M155 10 C 160 5, 170 25, 165,25z;
                    M155 10 C 160 5, 170 25, 165,30z;
                " />
                </path>
                <path d="M155 5 C 163 0, 170 15, 165,10z" fill="#E78484">
                    <animate repeatCount="indefinite" fill="#E78484" attributeName="d" dur="2s" attributeType="XML"
                        values="
                    M0,0;
                    M0,0;
                    M0,0;
                   
                    M155 5 C 158 0, 160 7, 160,10z;
                    M155 5 C 160 0, 163 10, 164,10z;
                    M155 5 C 163 0, 170 15, 165,10z;
                
                " />
                </path>

                <polygon points="20,5 45,150, 125,150 150,5" fill="none" stroke="#000" stroke-width="3" />

            </svg>
        </div>
    </div>

    <script src="./svg.js"></script>

</body>

</html>

코드 - JavaScript


function getRandom() {
  const randomNumber = Math.floor(Math.random() * (40 - 1) + 1);

  let randomText = document.getElementById("random");
  randomText.innerText = randomNumber;

  setCup(randomNumber);
}

function setCup(randomNumber) {
    if(randomNumber < 11){
        return drawCup("one");
    }
    if(randomNumber < 21){
        return drawCup("two");
    }
    if(randomNumber < 31){
        return drawCup("three");
    }
    if(randomNumber < 41){
        return drawCup("four");
    }
}

function drawCup(cupId) {
  let cup = document.querySelector("#" + cupId);
  let svg = cup.childNodes[1].cloneNode(true);

  let cupArea = document.getElementById("cupArea");
  // 자식요소 모두 삭제해서 대체하기
  let last;
  while (last = cupArea.lastChild) cupArea.removeChild(last);
  cupArea.appendChild(svg);
}


getRandom();
let interval = setInterval(getRandom, 5000);
profile
개발이 하고싶어요

0개의 댓글