๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
IT/JavaScript

[JavaScript] Chart.js ์ฐจํŠธ ๊ตฌํ˜„ํ•˜๊ธฐ (์‚ฌ์šฉ์ž๊ฐ€ input์นธ์— ์—ฐ๋„ year๋ฅผ ์ž…๋ ฅํ–ˆ์„ ๋•Œ ์ฐจํŠธ ์ƒ‰ ๋ณ€ํ•˜๋Š” ํšจ๊ณผ ๊ตฌํ˜„ํ•˜๊ธฐ) (์ฆ๊ฐ๋ฅ  ๊ณ„์‚ฐ ํ•จ์ˆ˜ ๊ตฌํ˜„, ์ˆซ์ž๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅ)

by ITyranno 2024. 1. 5.
728x90
๋ฐ˜์‘ํ˜•

 

 

 

 

 

 

 

ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์„ธ๊ณ„๋ฅผ ํƒ๊ตฌํ•ฉ์‹œ๋‹ค.

 

 

 

 

 

 

 

 

Chart.js ์ฐจํŠธ ๊ตฌํ˜„ํ•˜๊ธฐ, ์ฆ๊ฐ๋ฅ  ๊ณ„์‚ฐ ํ•จ์ˆ˜ ๊ตฌํ˜„ํ•˜๊ธฐ

 

JavaScript์˜ Chart.js๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์›นํŽ˜์ด์ง€์— ์ฐจํŠธ๋ฅผ ์ถœ๋ ฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

 

 

 

 

๊ตฌํ˜„ ํ™”๋ฉด

 

์ €๋Š” ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์—ฐ๋„๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ์ฆ๊ฐ๋ฅ ์„ ๊ณ„์‚ฐํ•ด ์ถœ๋ ฅํ•˜๊ณ ,

์ฐจํŠธ์˜ ํ•ด๋‹น ์—ฐ๋„ ๊ทธ๋ž˜ํ”„์— ์ƒ‰์ด ๋ณ€ํ•˜๋Š” ํšจ๊ณผ๋ฅผ ์ ์šฉํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค.

 

์ด๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด powerprice.html์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์›ํ•˜๋Š” year๋ฅผ ์ž…๋ ฅ ๋ฐ›๊ณ ,

powerprice.js์—์„œ ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ๊ฐ’์„ ๊ณ„์‚ฐํ•œ ํ›„ updateChart(year)๋ฅผ ์š”์ฒญํ•˜๊ณ ,

pChart.js์—์„œ year๊ฐ’์„ ๋ฐ›์•„ ์ฐจํŠธ์˜ ์ƒ‰์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

 

 

๊ฐ’์ด ๋‚˜์˜ฌ ๋•Œ ๊ทธ๋ž˜ํ”„๊ฐ€ ์•„๋ž˜๋กœ ๋‚ด๋ ค๊ฐ€๋Š” ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ๋Š”๋ฐ, css์—์„œ min-height๋ฅผ 3rem ์„ค์ •ํ•˜์—ฌ ๊ณต๊ฐ„์„ ๋ฐฐ์ •ํ•˜์—ฌ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

 

 

 

 

 

 

์ž‘์„ฑ ์ฝ”๋“œ

 

 

์ฒ˜์Œ ์ž‘์„ฑํ–ˆ์„ ๋•Œ, ๋ชจ๋“  ์ฐจํŠธ.js์ฝ”๋“œ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ž…๋ ฅํ•ด์„œ ์ถœ๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡๊ฒŒ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ ๊ฒฐ๊ณผ ์ค‘๋ณต๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํŒŒ์ผ์— ๋ฐ˜๋ณตํ•˜์—ฌ ์ž…๋ ฅํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋ž˜์„œ ๋ฐ์ดํ„ฐ.js ํŒŒ์ผ์„ ๋”ฐ๋กœ ๋งŒ๋“  ํ›„ export const๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋‚ด๋ณด๋‚ด๊ธฐํ•˜๊ณ ,

import๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ ์ค‘๋ณต ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

 

 

 

powerprice.html

 

 

์ฐจํŠธ๊ฐ€ ๋‚˜ํƒ€๋‚˜๋Š” ์ฝ”๋“œ

<body>

<div style="
        width: 60vw;
        height: 60vh;
        display: flex;
        justify-content: center;
        align-items: center;
        margin-top: 3rem;
      ">
  <!--์ฐจํŠธ๊ฐ€ ๊ทธ๋ ค์งˆ ๋ถ€๋ถ„-->
  <canvas id="priceChart"></canvas>
</div>

</body>

 

 

 

 

 

์‚ฌ์šฉ์ž๊ฐ€ ์—ฐ๋„๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ์ž…๋ ฅ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋Š” ์ฝ”๋“œ

 

์ˆซ์ž๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•˜๋„๋ก ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•

 

์ฒ˜์Œ์—๋Š” input type์„ text๋กœ ์ง€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋žฌ๋”๋‹ˆ ์‚ฌ์šฉ์ž๊ฐ€ ํ•œ๊ธ€์ด๋‚˜ ์˜์–ด ํ…์ŠคํŠธ ๋˜ํ•œ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

 

์ •๊ทœ์‹์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์œผ๋‚˜, ์ €๋Š” input type์„ number๋กœ ๋ฐ”๊พธ๋Š” ๋ฐฉ์‹์œผ๋กœ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ ๊ฒฐ๊ณผ, ์ˆซ์ž ์™ธ์—๋Š” ๋ฌธ์ž๊ฐ€ ์ž‘์„ฑ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

 

 

<body>
  <div id="powerprice-container">
    <div id="input-container">
      <input type="number" id="powerprice-yearInput" min="0" placeholder="1955๋…„~2070๋…„ ์‚ฌ์ด์˜ ์—ฐ๋„๋งŒ ์ž…๋ ฅํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค." />
      <select class="year-dropdown" id="year-dropdown" onchange="updateYearInput()">
        <script>
          for (let i = 1955; i <= 2070; i++) {
            document.write('<option value="' + i + '">' + i + '</option>');
          }
        </script>
      </select>
      <button onclick="getPowerPrice()">ํ™•์ธ</button>
    </div>
    <p id="powerprice-result"></p> <!-- ์—ฌ๊ธฐ์— ๊ฒฐ๊ณผ๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. -->
  </div>
</body>

 

 

 

 

 

powerPriceData.js

 

1955~2022๋…„์˜ ๋ฐ์ดํ„ฐ๋Š” ์‹ค์ œ ๋ฐ์ดํ„ฐ์ž…๋‹ˆ๋‹ค.

2023~2070๋…„์˜ ๋ฐ์ดํ„ฐ๋Š” Python์˜ scikit-learn ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ

์„ ํ˜•ํšŒ๊ท€(Linear Regression) ๋ฐฉ์‹์œผ๋กœ ์˜ˆ์ธกํ•œ ํ›„ ์ˆ˜์น˜ํ™”ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

export const๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋‚ด๋ณด๋ƒˆ์Šต๋‹ˆ๋‹ค.

(์‹ค์ œ๋กœ๋Š” 1955~2070๋…„์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ์ž…๋ ฅ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.)

export const powerPriceData = {
    1955: 3,
    1956: 3,
};

 

 

 

 

powerprice.js

 

import๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.

2022๋…„์˜ ๋ฐ์ดํ„ฐ์™€ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ์—ฐ๋„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋น„๊ตํ•˜์—ฌ ์ „๊ธฐ ๋‹จ๊ฐ€ ์ฆ๊ฐ๋ฅ ์„ ๊ณ„์‚ฐํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

 

์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅ ๋ฒ„ํŠผ, Enter ํ‚ค ์–ด๋–ค ๊ฒƒ์„ ๋ˆ„๋ฅด๋”๋ผ๋„ ๊ฐ’์ด ๋‚˜์˜ค๋„๋ก ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

import { powerPriceData } from './powerPriceData.js';

window.updateYearInput = function () {
  var yearInput = document.getElementById("powerprice-yearInput");
  var yearDropdown = document.getElementById("year-dropdown");

  // ์„ ํƒํ•œ ์—ฐ๋„๋ฅผ ์ž…๋ ฅ ์ฐฝ์— ์„ค์ •
  yearInput.value = yearDropdown.value;
}

window.onload = function () {
  document.getElementById("powerprice-yearInput")
    .addEventListener("keydown", window.handleKeyPress);
};

window.handleKeyPress = function (event) {
  // ์—”ํ„ฐ ํ‚ค๋ฅผ ๋ˆŒ๋ €์„ ๋•Œ
  if (event.key === "Enter") {
    getPowerPrice();
  }
}

window.toggleYearDropdown = function () {
  var yearDropdown = document.getElementById("year-dropdown");

  // ํ† ๊ธ€ ๋กœ์ง๋งŒ ์ˆ˜ํ–‰
  yearDropdown.style.display =
    yearDropdown.style.display === "none" ? "block" : "none";
}

window.getPowerPrice = function () {
  let year = document.getElementById("powerprice-yearInput").value;

  // ๋นˆ ์นธ ์ฒดํฌ
  if (year.trim() === "") {
    document.getElementById("powerprice-result").innerText = "์—ฐ๋„๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.";
    return;
  }


  let price = powerPriceData[year];

  if (price === undefined) {
    document.getElementById("powerprice-result").innerText =
      year + "๋…„์˜ ๋ฐ์ดํ„ฐ๋Š” ์•„์ง ์ค€๋น„๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.";
  } else {
    let baseYear = 2022;
    let basePrice = powerPriceData[baseYear];
    let increaseRate = (((price - basePrice) / basePrice) * 100).toFixed(2);

    if (year >= 1955 && year <= 2022) {
      let priceComparison =
        increaseRate > 0 ? "๋†’์€ ๊ฐ€๊ฒฉ์ž…๋‹ˆ๋‹ค." : "๋‚ฎ์€ ๊ฐ€๊ฒฉ์ž…๋‹ˆ๋‹ค.";

      document.getElementById("powerprice-result").innerText =
        year +
        "๋…„์˜ ์ „๊ธฐ ๋‹จ๊ฐ€๋Š” " +
        price +
        " kWh/๋ช…์œผ๋กœ, " +
        baseYear +
        "๋…„ ๋Œ€๋น„ " +
        Math.abs(increaseRate) +
        "% " +
        priceComparison;
    } else {
      document.getElementById("powerprice-result").innerText =
        year +
        "๋…„์˜ ์˜ˆ์ƒ ์ „๊ธฐ ๋‹จ๊ฐ€๋Š” " +
        price +
        " kWh/๋ช…์œผ๋กœ, " +
        baseYear +
        "๋…„ ๋Œ€๋น„ " +
        increaseRate +
        "% ์ƒ์Šนํ•ฉ๋‹ˆ๋‹ค.";
    }
    updateChart(year);
  }
}

 

 

 

 

pChart.js

 

import๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.

window.updateChart๋ถ€ํ„ฐ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ year๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

 

// pChart.js
import { powerPriceData } from './powerPriceData.js';

const priceChartData = {
  labels: Object.keys(powerPriceData),
  datasets: [
    {
      label: "์ „๋ ฅ ๋‹จ๊ฐ€ (kWh/์›)",
      data: Object.values(powerPriceData),
      backgroundColor: Object.keys(powerPriceData).map(() => "rgba(0, 0, 0, 0.07)"), // ๊ธฐ๋ณธ ์ƒ‰์ƒ์œผ๋กœ ๋ฐฐ์—ด ์ฑ„์šฐ๊ธฐ
      borderColor: "rgba(206, 41, 91, 0.624)", // ๋ง‰๋Œ€ ํ…Œ๋‘๋ฆฌ ์ƒ‰์ƒ ์„ค์ •
      borderWidth: 1,
    },
  ],
};

const config = {
  type: "bar",
  data: priceChartData, // 'powerPriceData'๋ฅผ 'priceChartData'๋กœ ๋ณ€๊ฒฝ
  options: {
    responsive: true,
    scales: {
      x: {
        type: "linear",
        position: "bottom",
      },
      y: {
        beginAtZero: true,
      },
    },
    plugins: {
      legend: {
        display: true,
        position: "top",
      },
      title: {
        display: true,
        text: "์ „๋ ฅ ๊ฐ€๊ฒฉ ๊ทธ๋ž˜ํ”„",
      },

    },
  },
};

// Canvas ์š”์†Œ ๊ฐ€์ ธ์˜ค๊ธฐ
const ctx = document.getElementById("priceChart").getContext("2d");

// Chart ์ƒ์„ฑ
const priceChart = new Chart(ctx, config);

window.updateChart = function (year) {
  let color;
  if (year < 2022) {
    color = "red";
  } else if (year < 2040) {
    color = "blue";
  } else {
    color = "green";
  }

  let price = powerPriceData[year];
  if (price === undefined) {
    alert(year + "๋…„๋„์˜ ๋ฐ์ดํ„ฐ๋Š” ์•„์ง ์ค€๋น„๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.");
  } else {
    // ํ˜„์žฌ ์—ฐ๋„๊ฐ€ labels ๋ฐฐ์—ด์— ์žˆ๋Š” ์œ„์น˜๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.
    let index = priceChart.data.labels.indexOf(year.toString());
    if (index === -1) {
      // ์—ฐ๋„๊ฐ€ ์•„์ง labels ๋ฐฐ์—ด์— ์—†๋‹ค๋ฉด, ์—ฐ๋„์™€ ๋ฐ์ดํ„ฐ, ์ƒ‰์ƒ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
      priceChart.data.labels.push(year.toString());
      priceChart.data.datasets[0].data.push(price);
      priceChart.data.datasets[0].backgroundColor.push(color);
    } else {
      // ์—ฐ๋„๊ฐ€ ์ด๋ฏธ labels ๋ฐฐ์—ด์— ์žˆ๋‹ค๋ฉด, ํ•ด๋‹น ์œ„์น˜์˜ ๋ฐ์ดํ„ฐ์™€ ์ƒ‰์ƒ๋งŒ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.
      priceChart.data.datasets[0].data[index] = price;
      priceChart.data.datasets[0].backgroundColor[index] = color;
    }
    priceChart.update();
  }
}

 

 

 

 

 

 

 

๊ตฌํ˜„ ํ™”๋ฉด์„ ๋” ์ƒ์„ธํžˆ ํ™•์ธํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์•„๋ž˜ ์‚ฌ์ดํŠธ ์ฐธ๊ณ  ๋ฐ”๋ž๋‹ˆ๋‹ค.

 

 

https://ityrannosaurus.github.io/power/

 

๋‚ด์ผ์˜ ์ „๊ธฐ์„ธ

scikit-learn ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ ํ˜•ํšŒ๊ท€(Linear Regression) ๋ฐฉ์‹์œผ๋กœ ์˜ˆ์ธก์„ ์ˆ˜ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ 2070๋…„๊นŒ์ง€์˜ ์˜ˆ์ธก๊ฐ’์„ ์ถœ๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค.

ityrannosaurus.github.io

 

 

 

 

728x90
๋ฐ˜์‘ํ˜•

loading