Animates SVG Donut (doughnut) Chart

by moob

HTML

<svg width="35px" height="34px" viewBox="-1 0 35 34" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <!-- Generator: Sketch 3.8.3 (29802) - http://www.bohemiancoding.com/sketch -->
    <desc>Created with Sketch.</desc>
    <defs>
        <circle id="path-1" cx="16.7813362" cy="16.7813362" r="16.7813362"></circle>
        <mask id="mask-2" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="33.5626723" height="33.5626723" fill="white">
            <use xlink:href="#path-1"></use>
        </mask>
        <circle id="path-3" cx="16.7813362" cy="16.7813362" r="16.7813362"></circle>
        <mask id="mask-4" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="33.5626723" height="33.5626723" fill="white">
            <use xlink:href="#path-3"></use>
        </mask>
    </defs>
    <g id="rings" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <use id="backg" stroke="#979797" mask="url(#mask-2)" stroke-width="10" transform="translate(16.781336, 16.781336) rotate(90.000000) translate(-16.781336, -16.781336) " xlink:href="#path-1"></use>
        <use id="foreg" stroke="" mask="url(#mask-4)" stroke-width="10" stroke-dasharray="60,100" transform="translate(16.781336, 16.781336) scale(-1, 1) rotate(-180.000000) translate(-16.781336, -16.781336) " xlink:href="#path-3"></use>
    </g>
</svg>



<svg id="donutBase" viewBox="0 0 34 34" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <title>Doughnut</title>
    <desc>Calculated to have diameter of 100 to make things easy</desc>
    <defs>
        <circle id="background-ring" cx="16.7813362" cy="16.7813362" r="16.7813362"></circle>
        <linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient">
            <stop stop-color="#FB0071" offset="0%"></stop>
            <stop stop-color="#5C0873" offset="100%"></stop>
       ...

CSS

#donutBase {
    border: 0;
    clip: rect(0 0 0 0);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    padding: 0;
    position: absolute;
    width: 1px;
}

svg:not(:root) {
    overflow: hidden;
}

svg .backg {
    stroke: #ccc;
    mask: url(#ring-mask);
    fill-opacity: 0;
    stroke-opacity: 1;
}

svg .foreg {
    stroke: url(#linearGradient);
    mask: url(#ring-mask);
    fill-opacity: 0;
    stroke-opacity: 1;
    stroke-dasharray: 100px;
    transition: stroke-dashoffset 1.5s cubic-bezier(0.25, 0.1, 0.23, 0.97);
}

svg .foreg2 {
    stroke: url(#linearGradient2);
    mask: url(#ring-mask);
    fill-opacity: 0;
    stroke-opacity: 1;
    stroke-dasharray: 100px;
    transition: stroke-dashoffset 1.5s cubic-bezier(0.25, 0.1, 0.23, 0.97);
}

#donutWrapper {
    width: 50%;
}

div ~ svg {
    width: 100%;
}

#chart2 .backg {
    stroke: #fff;
}

#chart3, #chart4, #chart5 {
    width: 50px;
}
#chart4 .backg {
    stroke: #eee;
}
#chart6 {width:100px;}

/* override a gradient:
#linearGradient2 stop {
 stop-color:#005C08; 
} 
#linearGradient2 stop + stop {
   stop-color:#00FB00;
} */

JavaScript

(function() {
    var foregs = document.querySelectorAll(".foreg"),
        x = document.getElementById("x"),
        fnc = function() {
            for (i = 0; i < foregs.length; ++i) {
                var r = (Math.random() * 100);
                foregs[i].setAttribute("stroke-dashoffset", r + "px");
                if (foregs[i].nextSibling.nextSibling) {
                    var nx = foregs[i].nextSibling.nextSibling;
                    console.log(nx);
                    nx.setAttribute("stroke-dashoffset", ((r - 100)-1) + "px");
                }
            }
        };
    x.addEventListener("click", fnc, false);
})();