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>
<div id="speedtest">
	<svg id="gauge" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
		<path style="fill: #e31212;" d="M12.9,75.5c0.3,0.5,0.7,0.9,1,1.4l7.6-5.7c-0.3-0.4-0.5-0.7-0.8-1.1L12.9,75.5z"/>
		<path style="fill: #ea1f39; display: none;" d="M9.3,69.3c0.3,0.5,0.5,1,0.8,1.5l8.4-4.4c-0.2-0.4-0.4-0.8-0.6-1.2L9.3,69.3z"/>
		<path style="fill: #f12d60; display: none;" d="M6.7,62.4C6.9,62.9,7,63.5,7.2,64l9.1-3c-0.1-0.4-0.3-0.8-0.4-1.2L6.7,62.4z"/>
		<path style="fill: #f83c85; display: none;" d="M5.3,55.2c0,0.6,0.1,1.1,0.2,1.7l9.4-1.5c-0.1-0.4-0.1-0.9-0.2-1.3L5.3,55.2z"/>
		<path style="fill: #ff4ba8; display: none;" d="M5,47.9c0,0.6,0,1.1,0,1.7l9.5,0.1c0-0.5,0-0.9,0-1.4L5,47.9z"/>
		<path style="fill: #fb3eb2; display: none;" d="M5.9,40.7c-0.1,0.6-0.2,1.1-0.3,1.7L15,44c0.1-0.4,0.2-0.9,0.2-1.3L5.9,40.7z"/>
		<path style="fill: #f732bf; display: none;" d="M8,33.7c-0.2,0.5-0.4,1.1-0.6,1.6l9,3.1c0.1-0.4,0.3-0.9,0.5-1.3L8,33.7z"/>
		<path style="fill: #f226cd; display: none;" d="M11.2,27.1c-0.3,0.5-0.5,1-0.8,1.5l8.3,4.6c0.2-0.4,0.4-0.8,0.7-1.2L11.2,27.1z"/>
		<path style="fill: #ee1adc; display: none;" d="M15.5,21.2c-0.4,0.4-0.8,0.9-1.1,1.3l7.5,5.8c0.3-0.4,0.6-0.7,0.9-1.1L15.5,21.2z"/>
		<path style="fill: #ae19de; display: none;" d="M20.6,16c-0.5,0.3-0.9,0.7-1.3,1.1l6.5,7c0.3-0.3,0.6-0.6,1-0.9L20.6,16z"/>
		<path style="fill: #6618cd; display: none;" d="M26.4,11.7c-0.5,0.3-0.9,0.6-1.4,0.9l5.3,7.9c0.3-0.2,0.7-0.5,1-0.7L26.4,11.7z"/>
		<path style="fill: #2716bd; display: none;" d="M33,8.3c-0.6,0.2-1.1,0.5-1.6,0.7l3.9,8.7c0.4-0.2,0.9-0.4,1.3-0.6L33,8.3z"/>
		<path style="fill: #1537ac; display: none;" d="M39.9,6.1c-0.5,0.1-1.1,0.3-1.6,0.4l2.5,9.2c0.4-0.1,0.8-0.2,1.2-0.3L39.9,6.1z"/>
		<path style="fill: #2061c1; display: none;"...

CSS

html, body {
  height: 100%;
}

body {
  background-image: linear-gradient(rgba(0, 0, 0, 0.25), rgba(255, 255, 255, 0.25) 50%, rgba(255, 255, 255, 0) 50%), linear-gradient(#e31212, #e31212 50%, #fff 50%);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "Nunito", sans-serif;
}

#speedtest {
  position: relative;
  width: 400px;
  height: 400px;
  padding: 20px;
  border-radius: 6px;
  box-sizing: border-box;
}
#speedtest #gauge {
  width: 100%;
  height: 100%;
  padding: 12px;
  background: #fff;
  border-radius: 50%;
  box-shadow: 0 0 32px rgba(21, 55, 172, 0.25), inset 0 -192px 192px -240px #e31212;
  box-sizing: border-box;
}
#speedtest #gauge path:first-child {
  opacity: 1 !important;
  display: block !important;
}
#speedtest #gauge-label {
  position: absolute;
  top: 47.5%;
  left: 50%;
  font-size: 64px;
  transform: translate(-50%, -50%);
  color: #e31212;
}
#speedtest #gauge-label:after {
  content: "Mbit/s";
  position: absolute;
  font-size: 35%;
  bottom: 5px;
  left: 50%;
  transform: translate(-50%, 100%);
}
#speedtest:before, #speedtest:after {
  display: block;
  position: absolute;
  bottom: 25%;
  font-family: inherit;
  font-size: 14px;
  color: #9198af;
}
#speedtest:before {
  content: "0";
  left: 28%;
}
#speedtest:after {
  content: "100";
  right: 28%;
}

JavaScript

var delay = 2000, value = 0, valueStore = 0, tick = 1, tickStore = 1, tickDiff = 0, tickDiffValue = 0;

function valBetween(v, min, max) {
    return Math.min(max, Math.max(min, v));
}

function loop() {
    value = Math.ceil(Math.random() * 100);
    tick = valBetween(Math.ceil((value / 100) * 28), 1, 28);
    tickDiff = Math.abs(tick - tickStore);
    tickDiffValue = Math.abs(value - valueStore) / tickDiff;
    console.log("tickDiff: " + tickDiffValue + " * " + tickDiff + " = " + (tickDiffValue * tickDiff));

    var counter = 0, valueStoreTemp = valueStore, tickStoreTemp = tickStore;

    var gauge = document.getElementById('gauge');
    var gaugePaths = gauge.getElementsByTagName('path');

    if (value > valueStore) {
        for (var i = tickStoreTemp; i <= tick; i++) {
            (function (i) {
                setTimeout(function () {
                    gauge.style.boxShadow = '0 0 32px rgba(21, 55, 172, 0.25), inset 0 -192px 192px -240px ' + gaugePaths[i - 1].style.fill + ', inset 0 0 2px -1px ' + gaugePaths[i - 1].style.fill;
                    gaugePaths[i - 1].style.display = 'block';
                    document.getElementById('gauge-label').style.color = gaugePaths[i - 1].style.fill;
                    document.getElementById('gauge-label').textContent = Math.ceil(valueStoreTemp + (tickDiffValue * Math.abs(tickStoreTemp - i)));
                    if (i == tick) { document.getElementById('gauge-label').textContent = value; }
                }, 50 * counter);
                counter++;
            }(i));
        }
    } else if (value < valueStore) {
        for (var i = tickStoreTemp; i >= tick; i--) {
            (function (i) {
                setTimeout(function () {
                    gauge.style.boxShadow = '0 0 32px rgba(21, 55, 172, 0.25), inset 0 -192px 192px -240px ' + gaugePaths[i - 1].style.fill + ', inset 0 0 2px -1px ' + gaugePaths[i - 1].style.fill;
                    gaugePaths[i - 1].style.display = 'none';
                   ...