CSS&JS/✨개인 프로젝트

그래프 생성기 - windrose, bar, pie

arancia_ 2021. 7. 30. 17:48

https://ohikmyeong.github.io/windrose

 

WindRose, Pie, Bargraph 만들기

 

ohikmyeong.github.io

 

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>WindRose</title>
<link href="./css/ipt.css" rel="stylesheet" type="text/css"/>
<link href="./css/windrose.css" rel="stylesheet" type="text/css"/>
<script src="./js/windrose.js" type="module"></script>
</head>
<body>

<nav>
    <a href="./WindRose.html">WindRose</a>
    <a href="./PieGraph.html">PieGraph</a>
    <a href="./BarGraph.html">BarGraph</a>
</nav>

<section id="sect_opt">
    <label id="lbl-check">
        <input type="checkbox" id="is-rel" checked/>
        <span class="lbl">상대값 그래프 만들기</span>
    </label>

    <select id="sel">
        <option value="n1" selected>N1</option>
        <option value="n2">N2</option>
        <option value="n3">N3</option>
        <option value="n4">N4</option>
        <option value="n5">N5</option>
        <option value="n6">N6</option>
        <option value="n7">N7</option>
        <option value="n8">N8</option>
        <option value="n9">N9</option>
        <option value="n10">N10</option>
        <option value="n11">N11</option>
        <option value="n12">N12</option>
        <option value="n13">N13</option>
        <option value="n14">N14</option>
        <option value="n15">N15</option>
        <option value="n16">N16</option>
        <option value="n17">N17</option>
        <option value="n18">N18</option>
        <option value="n19">N19</option>
        <option value="n20">N20</option>
    </select>
</section>

<section id="sect_ipt">
    <label>
        <input value="1.3" type="number" placeholder="N" id="ipt-M1"/>
        <span class="lbl">M1</span>
    </label>
    <label>
        <input value="4" type="number" placeholder="NNE" id="ipt-M2"/>
        <span class="lbl">M2</span>
    </label>
    <label>
        <input value="8.3" type="number" placeholder="NE" id="ipt-M3"/>
        <span class="lbl">M3</span>
    </label>
    <label>
        <input value="8.5" type="number" placeholder="ENE" id="ipt-M4"/>
        <span class="lbl">M4</span>
    </label>
    <!--  -->

    <label>
        <input value="12.4" type="number" placeholder="E" id="ipt-M5"/>
        <span class="lbl">M5</span>
    </label>
    <label>
        <input value="18.3" type="number" placeholder="ESE" id="ipt-M6"/>
        <span class="lbl">M6</span>
    </label>
    <label>
        <input value="23" type="number" placeholder="SE" id="ipt-M7"/>
        <span class="lbl">M7</span>
    </label>
    <label>
        <input value="13.3" type="number" placeholder="SSE" id="ipt-M8"/>
        <span class="lbl">M8</span>
    </label>
    <!--  -->

    <label>
        <input value="5.2" type="number" placeholder="S" id="ipt-M9"/>
        <span class="lbl">M9</span>
    </label>
    <label>
        <input value="3.6" type="number" placeholder="SSW" id="ipt-M10"/>
        <span class="lbl">M10</span>
    </label>
    <label>
        <input value="3" type="number" placeholder="SW" id="ipt-M11"/>
        <span class="lbl">M11</span>
    </label>
    <label>
        <input value="1.1" type="number" placeholder="WSW" id="ipt-M12"/>
        <span class="lbl">M12</span>
    </label>
    <!--  -->

    <button id="btn">점찍기</button>
</section><!-- sect_ipt -->

<section id="sect_graph-windrose">

    <img src="./img/windrose.svg" alt="12각형" class="polygon">
    
    <div id="line-M1" style="--i:0;"><span class="dot"></span></div>
    <div id="line-M2" style="--i:1;"><span class="dot"></span></div>
    <div id="line-M3" style="--i:2;"><span class="dot"></span></div>
    <div id="line-M4" style="--i:3;"><span class="dot"></span></div>

    <div id="line-M5" style="--i:4;"><span class="dot"></span></div>
    <div id="line-M6" style="--i:5;"><span class="dot"></span></div>
    <div id="line-M7" style="--i:6;"><span class="dot"></span></div>
    <div id="line-M8" style="--i:7;"><span class="dot"></span></div>

    <div id="line-M9" style="--i:8;"><span class="dot"></span></div>
    <div id="line-M10" style="--i:9;"><span class="dot"></span></div>
    <div id="line-M11" style="--i:10;"><span class="dot"></span></div>
    <div id="line-M12" style="--i:11;"><span class="dot"></span></div>

</section><!-- sect_graph -->

</body>
</html>

 

CSS - 공통

@charset "utf-8";
*{margin:0;padding:0;box-sizing:border-box;}
html,body{
    display:flex;flex-wrap:wrap;
    flex-direction:column;
    justify-content:center; align-items:center;
    width:100%;min-height:100vh;
    padding:1rem 0;
    background:#ccc;
    font-size:20px;
}

#sect_ipt{
    display:flex;flex-wrap:wrap;
    justify-content:space-evenly;
    position:relative;
    width:90%; max-width:500px;
    padding:0 .5rem 1rem;
    background:rgba(255,255,255,.5);
}

label{
    display:block; position:relative;
    width:calc(33% - 1rem);
    padding-top:20px; margin:.5rem 0 0;}

[id ^= "ipt-"]{
    display:block;
    padding:.5rem 1rem;
    width:100%;
    border:1px solid #d2d2d2;
    font-family:inherit;font-size:14px;color:inherit;}

[id ^= "ipt-"] + .lbl{
    position:absolute;
    top:0;left:5px;
    font-size:12px;
}

#btn{
    display:block;position:relative;
    width:100%;
    padding:1em 2em; margin-top:1rem;
    background:teal;
    border:none;
    font-family:inherit;font-size:inherit; color:#fff;
    cursor:pointer;
}
#btn:hover{filter:brightness(.8);}

/*  */
#sect_opt{
    display:flex;flex-wrap:wrap;
    justify-content:space-between; align-items:center;
    position:relative;
    width:500px;}

/* 상대/절대 선택 */
[type="checkbox"]{
    position:absolute;overflow:hidden;
    width:1px;height:1px;
    clip:rect(0,0,0,0);}

#lbl-check{  
    display:block;position:relative;
    min-width:200px;
    font-family:inherit;font-size:14px;color:inherit;
    cursor:pointer;}


#lbl-check .lbl{
    display:block;position:relative;
    margin-bottom:1rem; padding-left:45px;
    border:1px solid #d2d2d2;
    font-size:1em; color:#999;}

#is-rel:checked + .lbl{font-weight:bold; color:#000;}

    #is-rel + .lbl::before{
        content:'';display:block;position:absolute;
        left:0;top:2px;
        width:24px;height:10px;
        border-radius:10px;
        border:3px solid #aaa;}

    #is-rel + .lbl::after{
        content:'';display:block;position:absolute;
        left:0;top:2px;
        width:10px; aspect-ratio:1/1;
        background:#ccc;
        border:3px solid #aaa;
        border-radius:50%;
        transition:transform .3s;}

    #is-rel:checked + .lbl::before{
        background:teal;
        border-color:teal;    }

    #is-rel:checked + .lbl::after{
        transform:translateX(100%);
        background:#fff;
        border-color:teal;    }

/* select */
select{
    padding:.5em;
    font-family:inherit;font-size:.875rem;
}

/* 그래프 영역--- */
[id ^= "sect_graph"]{
    position:relative;
    width:500px;
    margin:2rem auto 0;
    background:#fff;}

/* NAV */
nav{
    display:flex;flex-wrap:wrap;flex-direction:column;
    position:fixed;
    left:1rem;bottom:1rem;
    font-size:14px;
}

nav a{
    text-decoration:none;
    display:block;
    margin:.25em 0; padding:.5em;
    background:rgba(255,255,255,.5);
    text-align:center;font-weight:bold;color:#444;}

nav a:hover{
    background:teal;
    color:#fff;
}

 

CSS - 개별

@charset "utf-8";
#sect_graph-windrose{aspect-ratio:1/1;}

[id ^= "line-"]{
    position:absolute;
    top:0;left:calc(50% - 2px);
    transform-origin:center bottom;
    transform:rotate(calc(var(--i) * 30deg));
    width:5px; height:50%;
    background:transparent;
}

.dot{
    display:block;position:absolute; box-sizing:content-box;
    bottom:0;left:0;
    transform:translate(-25%, 50%);
    width:100%; aspect-ratio:1/1;
    background:rgb(0, 132, 255);
    border-radius:50%; border:2px solid #fff;
    box-shadow:0 0 5px rgba(0,0,0,.5);
}

 

JS - 공통 -CSV

export let obj_CSV = {
    test : [0, 4, 8, 12, 16, 20, 10, 10, 10, 24, 20, 20]
    , n1 : [1.3, 4, 8.3, 8.5, 12.4, 18.3, 23, 13.3, 5.2, 3.6, 3, 1.1]
    ,n2 : [0.7, 0.9, 0.9, 0.9, 1, 1.2, 2, 0.3, 0.3, 0.2, 1.2, 0.7]
    ,n3 : [2.1, 3.5, 4.5, 4.7, 6.7, 6.8, 9.1, 2.1, 1.5, 2.1, 2.2, 2.2]
    ,n4 : [0.4, 0.8, 1.6, 3.9, 6.8, 7.9, 11.1, 6.3, 2.6, 1.6, 0.9, 0.6]
    ,n5 : [1.4, 2.1, 2.9, 2.1, 2.1, 1.8, 1.7, 1.3, 2.2, 2.9, 3, 1.7]
    ,n6 : [1.5, 1, 1.4, 1, 0.8, 0.7, 0.5, 1.3, 3.3, 4.6, 3.3, 2.1]
    ,n7 : [1.4, 1.6, 1.1, 0.6, 0.8, 0.7, 0.4, 0.7, 1.6, 2.7, 2.5, 1.8]
    ,n8 : [2.8, 2.1, 2.6, 2.1, 2.8, 2.6, 3.2, 4.1, 10.1, 14.2, 9.9, 5.7]
    ,n9 : [0, 0, 0.1, 0.2, 0.4, 0.7, 0.6, 0.6, 0.1, 0, 0.1, 0.1]
    ,n10 : [0.1, 0.1, 0.3, 0.5, 0.9, 1.4, 1, 0.2, 0.2, 0.2, 0.1, 0.3]
    ,n11 : [0.2, 0.5, 0.9, 0.8, 1, 0.8, 0.9, 0.2, 0.1, 0.2, 0.2, 0.3]
    ,n12 : [0.7, 0.7, 1, 1.3, 1, 0.7, 0.8, 0.6, 1.1, 1.4, 1.3, 0.8]
    ,n13 : [0.1, 0.2, 0.7, 1.3, 2.6, 3.9, 4.2, 0.8, 0.2, 0.1, 0.2, 0.1]
    ,n14 : [0.9, 2.2, 2.8, 3.3, 3.2, 2.8, 3.1, 1, 1.1, 1.5, 1.3, 1.1]
    ,n15 : [0.3, 0.7, 1.2, 2.4, 3.2, 4.5, 5.6, 0.9, 0.3, 0, 0.4, 0.3]
    ,n16 : [0.5, 2.4, 5.6, 9.1, 12.1, 15.8, 20.4, 10.5, 4.5, 2, 1.2, 0.5]
    ,n17 : [0.1, 0.2, 0.8, 1.8, 3.7, 4.6, 2.1, 0.3, 0.5, 0.2, 0, 0]
    ,n18 : [0.1, 0.2, 0.3, 2, 3.9, 5.6, 5.8, 0.5, 0.1, 0, 0, 0]
    ,n19 : [0.4, 0.3, 0.3, 0.2, 0.4, 0.3, 0.2, 0.3, 0.5, 1.1, 0.9, 0.6]
    ,n20 : [1.3, 1.2, 1.9, 1.4, 1.6, 1.3, 0.8, 0.5, 1, 1.1, 0.8, 1]
}

export function put_CSV(obj,number){
    const ipts = document.querySelectorAll('[id ^= "ipt-"]');
    
    for(let i=0; i<ipts.length; i++){
        ipts[i].value = obj[number][i];
    }
}

 

 

JS - 공통 - 상대값

const ipt = document.querySelectorAll('[id ^= "ipt-"]');
const line = document.querySelectorAll('[id ^= "line-"]');
const dot = document.getElementsByClassName('dot');

let val_arr = [];
let per_arr = [];
let max = 20;


export function get_value(graph){
    reset_all();
    for(let val of ipt){ val_arr.push(Number(val.value));}

    if(graph == "pie-02"){
        display_pie_02();
        return;
    }

    get_max(graph);
}//get_value

function reset_all(){
    val_arr = [];
    per_arr = [];
    max = 0;
}//reset_all

function get_max(graph){
    for(let val of val_arr){
        if(max < val){max = val;}
    }
    console.log(max);
    put_percent(graph);
}//get_max

function put_percent(graph){
    
    for(let val of val_arr){
        const per = val * (graph == "bargraph" ? 90 : 100) / max;
        per_arr.push(per.toFixed(1));
    }
    switch(graph){
        case "windrose" :
            display_windrose();
            break;
        case "bargraph" :
            display_bargraph();
            break;
        case "pie" :
            display_pie();
            break;
        default : 
            break;
    }
}//put_percent

function display_windrose(){
    for(let i=0; i<per_arr.length; i++){
        dot[i].style.bottom = `${per_arr[i]}%`; 
    }
}//display_windrose

function display_bargraph(){
    console.log('asdfasf');
    for(let i=0; i<per_arr.length; i++){
        const span = line[i].getElementsByClassName('dot')[0];
        span.innerText = val_arr[i];
        line[i].style.height = `${per_arr[i]}%`; 
    }
}//display_bargraph

function display_pie(){
    for(let i=0; i<per_arr.length; i++){
        line[i].style.width = `${per_arr[i]}%`; 
        if(val_arr[i] == max){
            line[i].style.background = `var(--most)`;
        }
    }
}//display_pie


function display_pie_02(){
    let total = 0;
    for(let val of val_arr){total += val;}
    total = total.toFixed(2);
    let avg = 100 / total;
    avg = Math.round(avg);

    for(let val of val_arr){
        per_arr.push(val * avg);
    }

    let pie_arr = [];
    let add = 0;

    for(let per of per_arr){
        pie_arr.push(Math.round(per + add));
        add += per;
    }

    console.log(pie_arr);

    const pie02 = document.getElementById('pie-02');
    pie02.style.background = `
        conic-gradient(
            var(--m1) 0 ${pie_arr[0]}%, 
            var(--m2) ${pie_arr[0]}% ${pie_arr[1]}%, 
            var(--m3) ${pie_arr[1]}% ${pie_arr[2]}%,
            var(--m4) ${pie_arr[2]}% ${pie_arr[3]}%,
            var(--m5) ${pie_arr[3]}% ${pie_arr[4]}%,
            var(--m6) ${pie_arr[4]}% ${pie_arr[5]}%,
            var(--m7) ${pie_arr[5]}% ${pie_arr[6]}%,
            var(--m8) ${pie_arr[6]}% ${pie_arr[7]}%,
            var(--m9) ${pie_arr[7]}% ${pie_arr[8]}%,
            var(--m10) ${pie_arr[8]}% ${pie_arr[9]}%,
            var(--m11) ${pie_arr[9]}% ${pie_arr[10]}%,
            var(--m12) ${pie_arr[10]}% ${pie_arr[11]}%
            )
    `;
}//display_pie_02

 

JS - windrose.js

import * as common_r from './common_relative.js';
import * as common_ab from './common_absolute.js';
import {obj_CSV, put_CSV} from './csv.js';

const btn = document.getElementById('btn');
const is_rel = document.getElementById('is-rel');
const sel = document.getElementById('sel');

/* 실행 */
put_CSV(obj_CSV, "n1");

/* 버튼 누를시 */
btn.addEventListener('click',()=>{
    if(is_rel.checked){
        common_r.get_value('windrose');
    }else{
        common_ab.get_value('windrose');
    }
});

/*  */
sel.addEventListener('change',(e)=>{
    put_CSV(obj_CSV, e.target.value);
});