JSFiddle - React, Tailwind, and code Playground

Round Progress

by Jennifer Perrin

HTML

<ul class="da-stats-container">
    <li data-provide="circular" data-fill-color="#333" data-initial-value="85"
    data-max-value="98" data-label="Seeds Collected" style="width: 236px; height: 236px;"
    class="circular-stat" style="background: #000;">
        <canvas width="236" height="236" style="position: absolute; top: 0px; left: 0px;"
        class="back"></canvas>
        <canvas width="136" height="136" style=" position: absolute; top: 0px; left: 0px;"
        class="fill"></canvas>
        <canvas width="136" height="136" style="position: absolute; top: 0px; left: 0px; background-color: transparent;"
        class="front"></canvas><span class="digit-label">55/98</span><span class="text-label">Seeds Collected</span>
    </li>
    <li data-provide="circular" data-fill-color="#ea799b" daa-percent="true"
    data-initial-value="200" data-max-value="241" data-label="iPads Cloned"
    style="width: 236px; height: 236px;" class="circular-stat">
        <canvas width="236" height="236" style="position: absolute; top: 0px; left: 0px;"
        class="back"></canvas>
        <canvas width="236" height="236" style="position: absolute; top: 0px; left: 0px;"
        class="fill"></canvas>
        <canvas width="136" height="136" style="position: absolute; top: 0px; left: 0px;"
        class="front"></canvas><span class="digit-label">200/241</span><span class="text-label">iPads Cloned</span>
    </li>
    <li data-provide="circular" data-fill-color="#fab241" data-initial-value="124"
    data-max-value="523" data-label="Androids Bought" style="width: 236px; height: 236px;"
    class="circular-stat">
        <canvas width="236" height="236" style="position: absolute; top: 0px; left: 0px;"
        class="back"></canvas>
        <canvas width="136" height="136" style="position: absolute; top: 0px; left: 0px;"
        class="fill"></canvas>
        <canvas width="136" height="136" style="position: absolute; top: 0px; left: 0px;"
        class=""></canvas><span...

CSS

body {
    background:#eee
}
canvas, video {
    display: inline-block;
}
.da-stats-container li {
    background-color:#eee;
}
.da-stats-container {
    margin: 0;
    padding: 0;
    list-style: none;
    text-align: center;
}
.da-stats-container li {
    display: inline-block;
    margin: 0 5px 5px 5px;
    position: relative;
}
.circular-stat {
    position: relative;
}
.circular-stat .digit-label {
    top: 12.5%;
    width: 75%;
    padding: 20px 10px;
    font-size: 15px;
    font-weight: bold;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.circular-stat .digit-label, .circular-stat .text-label {
    display: inline-block;
    position: absolute;
    text-align: center;
    width: 75%;
    left: 12.5%;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    -o-box-sizing: border-box;
    -ms-box-sizing: border-box;
    box-sizing: border-box;
}
.circular-stat .text-label {
    font-family:Helvetica;
    top: 50%;
    left: 21.875%;
    width: 56.25%;
}
.front-2 {
    background: none;
    background-color: rgba(0, 0, 0, 0);
    height: 0px;
    width: 0px;
}

JavaScript

(function (c, e, l, j) {
    var d = function (a, b) {
        arguments.length && this.init(a, b);
    };
    d.CANVAS_NAMES = ["back", "fill", "front"];
    var i = d,
        f;
    f = l.createElement("canvas");
    f.getContext ? (f = f.getContext("2d"), f = (e.devicePixelRatio || 1) / (f.webkitBackingStorePixelRatio || f.mozBackingStorePixelRatio || f.msBackingStorePixelRatio || f.oBackingStorePixelRatio || f.backingStorePixelRatio || 1)) : f = 1;
    i.PIXEL_RATIO = f;
    i = ["ms", "moz", "webkit", "o"];
    for (f = 0; f < i.length && !e.requestAnimationFrame; f++) e.requestAnimationFrame = e[i[f] + "RequestAnimationFrame"], e.cancelAnimationFrame = e[i[f] + "CancelAnimationFrame"] || e[i[f] + "CancelRequestAnimationFrame"];
    e.requestAnimationFrame || (e.requestAnimationFrame = function (a) {
        return e.setTimeout(function () {
            a();
        }, 16);
    });
    e.cancelAnimationFrame || (e.cancelAnimationFrame = function (a) {
        clearTimeout(a);
    });
    var q = function (a) {
        arguments.length && this.init(a);
    };
    q.prototype = {
        attributes: {
            onLoop: null,
            afterStop: null,
            afterStopRequest: null,
            params: {},
            owner: null
        },
        init: function (a) {
            this.options = c.extend({}, this.attributes, a);
            this.animationHandle = null;
            this.loops = 0;
            this.stopRequested = !1;
        },
        start: function () {
            var a = this;
            this.animationHandle = e.requestAnimationFrame(function () {
                a.options.onLoop.apply(a.options.owner, [a._getThreadInfo()]) && a._loop();
            });
        },
        _getThreadInfo: function () {
            return {
                loops: ++this.loops,
                params: this.options.params,
                stopRequested: this.stopped
            };
        },
        _kill: function () {
           ...