CSS&JS/⚡Thinkers

[JS] 값 입력 받아서 JS로 svg 꺾은선 그래프 그리기

arancia_ 2026. 4. 3. 16:29

See the Pen 꺾은선 그래프 by Oh Ikmyeong (@dpffpself) on CodePen.

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="./style.css">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Pen</title>
  </head>
  <body>
  <article>
        <input type="text" id="dataInput" placeholder="예: 10, 50, 20, 90, 40" value="400,-400,200,0,100,600">
        <button onclick="randomValue()">RANDOM VALUE</button>
        <button onclick="drawChartWithValues()">DRAW GRAPH</button>
    </article>
 
    <div style="position:relative;width:100%;max-width:1600px;aspect-ratio:9/4;background:#ccc;">
        <svg id="chart" viewBox="0 0 900 400" preserveAspectRatio="xMidYMid meet"
            style="position:relative;width:100%;height:100%;background:#fff;border: 1px solid #ccc;">
            <polyline id="line" fill="none" stroke="blue" stroke-width="2" />
        </svg>
    </div>
    <script src="./script.js"></script>
  </body>
</html>
 
cs

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
 
body {
    display: flex;
    flex-flow: column nowrap;
    justify-content: center;
    align-items: center;
    gap: 20px;
    min-height: 100vh;
 
}
 
input,
button {
    font-family: inherit;
    font-size: inherit;
    padding: .5em 1em;
}
cs

JS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/**
 * 랜덤밸류
 * */
function randomValue() {
    const $ipt = document.getElementById("dataInput");
    const count = parseInt(Math.random() * 10 + 20);
    const values = [];
    const MAX = 400;
    const MIN = -400;
    for (let i = 0; i < count; i++) {
        const val = Math.round(Math.random() * (MAX - MIN) + MIN);
        values.push(val);
    }
    $ipt.value = values.join(", ");
}//randomValue
 
/**
 * 차트 그리기
 * */
function drawChartWithValues() {
    const $svg = document.getElementById("chart");
    /* svg reset */
    $svg.innerHTML = "";
 
    /*  */
    const svgWidth = 900;
    const svgHeight = 400;
 
    const input = document.getElementById('dataInput').value;
    const data = input.split(',').map(Number);
 
    const MAX = Math.max(...data);
    const MIN = Math.min(...data);
    const paddingX = 20;
    const paddingY = 20;
 
    const range = (MAX - MIN) || 1;
 
    // X축 간격 계산
    const xStep = (svgWidth - paddingX * 2/ (data.length - 1);
 
    // 데이터 배열을 SVG points 문자열로 변환
    const points = [];
 
    const get_y = (val = 0=> {
        return svgHeight - paddingY - ((val - MIN) / range) * (svgHeight - paddingY * 2);
    }
 
    data.forEach((val, i) => {
        /* 포인트 잡고 */
        const x = paddingX + i * xStep;
        const y = get_y(val);
        points.push(`${x},${y}`);
 
        // 2. 점(Circle) 그리기
        const $circle = document.createElementNS("http://www.w3.org/2000/svg""circle");
        $circle.setAttribute("cx", x);
        $circle.setAttribute("cy", y);
        $circle.setAttribute("r""4");
        $circle.setAttribute("fill""blue");
        $svg.appendChild($circle);
 
        // 3. 값(Text) 표기하기
        const $text = document.createElementNS("http://www.w3.org/2000/svg""text");
        $text.setAttribute("x", x);
        $text.setAttribute("y", y - 10); // 점보다 10px 위에 표시
        $text.setAttribute("text-anchor""middle"); // 텍스트 가운데 정렬
        $text.setAttribute("font-size""12");
        $text.textContent = val;
        $svg.appendChild($text);
    });
 
    // 4. 선(Polyline) 추가
    const $polyline = document.createElementNS("http://www.w3.org/2000/svg""polyline");
    $polyline.setAttribute("points", points.join(' '));
    $polyline.setAttribute("fill""none");
    $polyline.setAttribute("stroke""blue");
    $polyline.setAttribute("stroke-width""2");
 
    // 선을 점보다 뒤에 배치하기 위해 제일 앞에 삽입
    $svg.insertBefore($polyline, $svg.firstChild);
 
    // 0. 0을 기준으로 그려주면 좋을것 같아.
    const $zero = document.createElementNS("http://www.w3.org/2000/svg""polyline");
    $zero.setAttribute("points", [`0,${get_y(0)}`, `${svgWidth},${get_y(0)}`].join(' '));
    $zero.setAttribute("fill""none");
    $zero.setAttribute("stroke""#cccccc");
    $zero.setAttribute("stroke-width""1");
    $svg.insertBefore($zero, $svg.firstChild);
}//drawChartWithValues
cs