JSFiddle - React, Tailwind, and code Playground

by ckissi

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Design:
https://dribbble.com/shots/2987559-SmartHome-App-Dark -->
<div class="gauge" data-digit=60>
    <div class="gauge-outer"></div>
    <div class="gauge-inner"></div>
    <div class="gauge-digits"></div>
</div>

CSS

@charset "UTF-8";
body {
  background-color: #1c2039;
}

.gauge {
  position: relative;
  width: 7em;
  height: 5.8em;
  margin: 0.5em auto;
  font-size: 5em;
  direction: ltr;
}

.gauge-inner {
  position: relative;
  top: -4.85em;
  opacity: 0;
  transition: opacity 0.5s;
}
.gauge.load .gauge-inner {
  opacity: 1;
}
.gauge-inner .bar {
  left: 50%;
  position: absolute;
  transform-origin: 0 2.5em;
  width: 0.03em;
  height: 0.2em;
  background: rgba(255, 255, 255, 0.2);
}
.gauge-inner .bar.peak {
  height: 0.35em;
}

.gauge-outer {
  position: relative;
  height: 100%;
  margin-top: 0.3em;
}
.gauge-outer .bar {
  position: absolute;
  width: 0.05em;
  height: 0.7em;
  left: 50%;
  transform-origin: 0 3.43em;
  background-color: rgba(0, 0, 0, 0.2);
  opacity: 0;
  transition: opacity 0.5s;
}
.gauge.load .gauge-outer .bar {
  opacity: 1;
}

.gauge-digits {
  position: absolute;
  height: 81%;
  width: 70%;
  top: 1.3em;
  left: 50%;
  transform: translateX(-50%);
  color: rgba(255, 255, 255, 0.4);
  opacity: 0;
  transition: opacity 0.5s 0.5s;
}
.gauge.load .gauge-digits {
  opacity: 1;
}
.gauge-digits.scale {
  transform: translateX(-50%) scale(0.8);
}
.gauge-digits .digit {
  position: absolute;
  font-size: 0.4em;
  line-height: 0.2;
}
.gauge-digits .current-digit {
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-size: 1.5em;
  color: rgba(255, 255, 255, 0.9);
}
.gauge-digits .current-digit:after {
  content: "°";
}

JavaScript

document.addEventListener('DOMContentLoaded', function () {
    (function () {
        const points = 43;
        const radius = 257;
        const max = 100;
        const peaks = [10, 30, 50];
        const step = (max + 1) / points;
        const realPeaks = peaks.map(peak => Math.floor(peak * (1 / step)));
        const hueStep = 120 / points;

        const gaugeDigits = document.querySelector('.gauge-digits');

        const digit = parseInt(document.querySelector('.gauge').getAttribute('data-digit'));
        gaugeDigits.insertAdjacentHTML('beforeend', `<span class="digit current-digit count">0</span>`);

        for (let i = 0; i < points; i++) {
            const degree = i * (radius / (points - 1)) - radius / 2;
            const isPeak = realPeaks.indexOf(i) > -1;
            const gaugeInner = document.querySelector('.gauge-inner');
            gaugeInner.insertAdjacentHTML('beforeend', `<i class="bar${isPeak ? ' peak' : ''}" style="transform: rotate(${degree}deg)"></i>`);

            const intStep = Math.ceil(step * i);
            const intNextStep = Math.ceil(step * (i + 1));

            let styles = `transition-delay: ${ (i / digit) * (i / digit) + 1 }s;`;

            if (intStep <= digit) {
                styles += `background-color: hsl(${240 + i * hueStep}, 92%, 64%);`;
            }

            if (intStep > digit || (intStep <= digit && intNextStep <= digit)) {
                styles += `
                -webkit-transform: rotate(${degree}deg);
                -moz-transform: rotate(${degree}deg);
                -ms-transform: rotate(${degree}deg);
                -o-transform: rotate(${degree}deg);
                transform: rotate(${degree}deg);`;
            } else {
                if (intNextStep > digit)
                    styles += `
                    -webkit-transform: rotate(${degree}deg) translateY(-.3em);
                    -moz-transform: rotate(${degree}deg) translateY(-.3em);
                    -ms-transform:...