[따라만들기] 간트 차트

파송송계란빡 ㅣ 2022. 3. 2. 21:35

https://youtu.be/6-bGYmRSnYI

 

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>JavaScript for frontend developer</title>

  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div class="chart-wrapper">
    <ul class="chart-values">
      <li>sun</li>
      <li>mon</li>
      <li>tue</li>
      <li>wed</li>
      <li>thu</li>
      <li>fri</li>
      <li>sat</li>
    </ul>
    <ul class="chart-bars">
      <li data-duration="tue½-wed" data-color="#b03532">Task</li>
      <li data-duration="wed-sat" data-color="#33a8a5">Task</li>
      <li data-duration="sun-tue" data-color="#30997a">Task</li>
      <li data-duration="tue½-thu" data-color="#6a478f">Task</li>
      <li data-duration="mon-tue½" data-color="#da6f2b">Task</li>
      <li data-duration="wed-wed" data-color="#3d8bb1">Task</li>
      <li data-duration="thu-fri½" data-color="#e03f3f">Task</li>
      <li data-duration="mon½-wed½" data-color="#59a627">Task</li>
      <li data-duration="fri-sat" data-color="#4464a1">Task</li>
    </ul>
  </div>
  <script src="main.js"></script>
</body>

</html>
/* reset */
:root {
    --white : #fff;
    --divider : lightgray;
    --body : #f5f7f9;
}

* {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}

ul {
    list-style: none;
}

a {
    text-decoration: none;
    color: inherit;
}

body {
    background: var(--body);
    font-size: 16px;
    font-family: sans-serif;
    padding-top: 40px;
}

.chart-wrapper {
    max-width: 1150px;
    width: 95%;
    margin: 0 auto;
}


/*chart-values*/
.chart-values {
    position: relative;
    display: flex;
    margin-bottom: 20px;
    font-weight: bold;
    font-size: 1.2rem;
}

.chart-values li {
    flex : 1;
    min-width: 80px;
    text-align: center;
}

/*li마다 오른쪽에 선 그어주기(막네 빼고)*/
.chart-values li:not(:last-child) {
    position: relative;     /*li 에 relatevie 넣기*/
}

.chart-values li:not(:last-child)::before {
    content: "";
    position: absolute;
    right: 0;
    height: 510px;
    border-right: 1px solid var(--divider);
}

/*chart-bars*/
.chart-bars li{
    position: relative;
    color: var(--white);
    margin-bottom: 15px;
    font-size: 16px;
    border-radius: 20px;
    padding: 10px 20px;
    width: 0;
    opacity: 0;
    transition: all 0.6s linear 0.2s;
    
}

@media screen and (max-width : 600px) {
    .chart-bars li{
        padding: 10px;
    }
}
function createChart(event) {
    //opacity가 0에서 1로 올라오는 과정
    const days = document.querySelectorAll(".chart-values li");
    const tasks = document.querySelectorAll(".chart-bars li");
    //nodelist 는 배열이 아니다 array로 바꿔줘야 forEach를 사용가능
    const daysArray = [...days];


    // forEach기본 문법 : tasks.forEach(function(currentvalue, index, array){});
    tasks.forEach(el => {
        //변수 지정
        const duration = el.dataset.duration.split("-");    //data-duration의 -로 나눈다
        const startDay = duration[0];
        const endDay = duration[1];

        let left = 0;
        let width = 0;
        //1. 바(시작일)의 left 확인
        if (startDay.endsWith("½")) {
            //chart-bars값과 chart-values li 값이 매칭
            const filteredArray = daysArray.filter(day => day.textContent == startDay.slice(0, -1))
            left = filteredArray[0].offsetLeft + filteredArray[0].offsetWidth / 2;    //왼쪽에 있는 시작 값에 있는 1/2 가져오기
        } else {
            const filteredArray = daysArray.filter(day => day.textContent == startDay);
            left = filteredArray[0].offsetLeft;    //왼쪽에 있는 시작 값에 있는 1/2 가져오기
        }

        //2. 종료일을 이용해서 바의 width 확인
        if (endDay.endsWith("½")) {
            const filteredArray = daysArray.filter(day => day.textContent == endDay.slice(0, -1));
            width = filteredArray[0].offsetLeft + filteredArray[0].offsetWidth / 2 - left;
        } else {
            const filteredArray = daysArray.filter(day => day.textContent == endDay);
            width = filteredArray[0].offsetLeft + filteredArray[0].offsetWidth - left;
        }

        //left, width li css 지정
        el.style.left = `${left}px`;
        el.style.width = `${width}px`;

        if (event.type == "load") {
            el.style.backgroundColor = el.dataset.color;
            el.style.opacity = "1";
        }

    }); //tasks.forEach끝
}//createChart() 끝

window.addEventListener("load", createChart);   //다 로드되면
window.addEventListener("resize", createChart); //사이즈 작아질떄
[따라만들기] 간트 차트