JSFiddle - React, Tailwind, and code Playground

by moob

HTML

<p>
 This HTML is for demo only but is basically the same as you have in the project already. You shouldnt need to change any of your existing HTML, but the CSS and JS are new. 
</p>
<div class="coverage ldBar label-center" data-type="stroke" data-stroke="#e14f36" data-stroke-width="20" style="width:90px;height:90px;margin:auto"  data-preset="circle">

                    <svg xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid" width="100%" height="100%" viewBox="0 0 100 100"><defs><filter id="ldBar-91b5ccf4ecdb-filter" x="-1" y="-1" width="3" height="3"><feMorphology operator="dilate" radius="3"></feMorphology><feColorMatrix values="0 0 0 0 1    0 0 0 0 1    0 0 0 0 1    0 0 0 1 0" result="cm"></feColorMatrix></filter><mask id="ldBar-91b5ccf4ecdb-mask"><image xlink:href="" filter="url(#ldBar-91b5ccf4ecdb-filter)" x="0" y="0" width="100" height="100" preserveAspectRatio="xMidYMid"></image></mask><g><mask id="ldBar-91b5ccf4ecdb-mask-path"><path d="M50 10A40 40 0 0 1 50 90A40 40 0 0 1 50 10" fill="#fff" stroke="#fff" filter="url(#ldBar-91b5ccf4ecdb-filter)"></path></mask></g><clipPath id="ldBar-91b5ccf4ecdb-clip"><rect class="mask" fill="#000"></rect></clipPath><pattern id="ldBar-91b5ccf4ecdb-pattern" patternUnits="userSpaceOnUse" x="0" y="0" width="300" height="300"><image x="0" y="0" width="300" height="300"></image></pattern></defs><g><path d="M50 10A40 40 0 0 1 50 90A40 40 0 0 1 50 10" fill="none" class="baseline" stroke="#eeedee" stroke-width="20"></path></g><g><path d="M50 10A40 40 0 0 1 50 90A40 40 0 0 1 50 10" class="mainline" clip-path="" fill="none" stroke-width="20" stroke="#e14f36" stroke-dasharray="27.373398184204103 224.98930323181153"></path></g></svg><div class="ldBar-label">10.89</div></div>
                    
                    <div class="coverage ldBar label-center" data-type="stroke" data-stroke="#e14f36" data-stroke-width="20" style="width:90px;height:90px;margin:auto" data-value="17.98" data-preset="circle">

        ...

CSS

/* for demo only, you arlready have these elements styled */
div.ldBar {
  position:relative;
}
div.ldBar .ldBar-label {
  position:absolute;
  top:0; right:0; bottom:0; left:0;
  display: flex;
  justify-content: center;
  align-items: center;
  margin:0;
  padding:0;
}
div.ldBar .ldBar-label:after {
  content:"%";
}
div.ldBar svg {
  display: block;
}
/* end for demo only */
/* begin new stuff needed for animation */
div.ldBar[data-value] svg .mainline {
opacity:0;
}
div.ldBar svg .mainline.animate {
  opacity:1;
  stroke-dasharray: 252;
  -webkit-animation: draw 2s linear forwards;
  animation: draw 2s linear forwards;
}
@-webkit-keyframes draw {
  from {
    stroke-dashoffset: 252;
  }
}
@keyframes draw {
  from {
    stroke-dashoffset: 252;
  }
}

JavaScript

var $circumference = 252;
var t = setTimeout(animateDonut,1000);
function animateDonut(){
$(".ldBar[data-value]").each(function() {
  var $progress = $(this).find('svg .mainline');
  var $currentClass = $progress.attr('class');
  var $value = $(this).data('value');
  var $value2 =  Math.round($circumference - ($value * $circumference / 100));
  console.log($progress,$currentClass,$value,$value2);
  $progress.attr({
    "style": "stroke-dashoffset:" +$value2+"",
    "class": "animate "+$currentClass+"",
  });
  //$(this).siblings(".ldBar-label").text($value+"xxX");
  var $t = $(this).find(".ldBar-label");
  $t.text("");
  $({ Counter: 0 }).animate({ Counter: $value }, {
    duration: 2000,//this must match the @keyframes draw animation duration set
    easing: 'linear',
    step: function () {
      $t.text(this.Counter.toFixed(2));
    },
    complete: function() {
        $t.text($value);//need to ensure it has the correct value at the very end
    }
  });
});
}