SimpleGauge JS Live Example

HTML

<!doctype html>
<html lang="it">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Simple Gauge</title>
  </head>
  <body>
    <table border="1" id="data-table">
      <thead>
        <tr>
          <th>Max Value</th>
          <th>Current Value</th>
          <th>Gauge</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>100</td>
          <td>0</td>
          <td class="indicator-cell"></td>
        </tr>
        <tr>
          <td>100</td>
          <td>20</td>
          <td class="indicator-cell"></td>
        </tr>
        <tr>
          <td>100</td>
          <td>40</td>
          <td class="indicator-cell"></td>
        </tr>
        <tr>
          <td>100</td>
          <td>60</td>
          <td class="indicator-cell"></td>
        </tr>
        <tr>
          <td>100</td>
          <td>80</td>
          <td class="indicator-cell"></td>
        </tr>
        <tr>
          <td>100</td>
          <td>100</td>
          <td class="indicator-cell"></td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

CSS

.indicator-container {
  position: relative;
  width: 100px;
  height: 50px;
  padding: 10px 10px 0;
  overflow: hidden;
}
.indicator {
  position: relative;
  width: 100%;
  height: 100%;
  background: linear-gradient(to right, green, yellow, red);
  border: 1px solid #ccc;
  border-radius: 100px 100px 0 0;
}
.arrow,
.indicator-cut {
  position: absolute;
  bottom: 0;
  left: 50%;
  border-radius: 100px 100px 0 0;
}
.indicator-cut {
  width: 50px;
  height: 25px;
  background-color: #fff;
  border: 1px solid #ccc;
  transform: translateX(-50%);
}
.arrow {
  width: 3.5px;
  height: 55px;
  background-color: #000;
  transform-origin: bottom center;
  transform: translateX(-50%) rotate(-90deg);
  z-index: 1;
  box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.4);
}
.arrow.animate {
  transition: transform 1s 0.5s ease-in-out;
}

JavaScript

document.addEventListener("DOMContentLoaded", () => {
  const rows = document.querySelectorAll("#data-table tbody tr")

  rows.forEach((row) => {
    // HTML elements init
    const col1 = parseFloat(row.cells[0].innerText)
    const col2 = parseFloat(row.cells[1].innerText)

    const indicatorCell = row.querySelector(".indicator-cell")

    const indicatorContainer = document.createElement("div")
    indicatorContainer.classList.add("indicator-container")

    const indicator = document.createElement("div")
    indicator.classList.add("indicator")

    const arrow = document.createElement("div")
    arrow.classList.add("arrow")

    const indicatorCut = document.createElement("div")
    indicatorCut.classList.add("indicator-cut")

    indicatorContainer.appendChild(indicator)
    indicatorContainer.appendChild(arrow)
    indicatorContainer.appendChild(indicatorCut)

    indicatorCell.appendChild(indicatorContainer)

    // Calculate angles
    const angle = Math.max(-87, Math.min((col2 / col1 - 0.5) * 180, 87))

    // Apply animations
    arrow.style.transform = "translateX(-50%) rotate(-90deg)"

    requestAnimationFrame(() => {
      arrow.classList.add("animate")
      arrow.style.transform = `translateX(-50%) rotate(${angle}deg)`
    })
  })
})