Antonin Cezard
Antonin Cezard

Reputation: 2021

Adding a fill animation to a svg pie chart

I want to animate a pie chart with a dynamic and unknown value on load. Let's say I retrieve the value asap and transform it in a rounded percentage :

var percentage = Math.round(sum * 100 / total);

Then I put my value there :

<div class="pie animated" id="pie-get-percentage"></div>

$('#pie-get-percentage').html(percentage);

SVG

$(document).ready(function() {
    $('#pie-get-percentage').html(percentage);

    function $$(selector, context) {
        context = context || document;
        var elements = context.querySelectorAll(selector);
        return Array.prototype.slice.call(elements);
    }

    $$('.pie').forEach(function(pie) {
        var p = parseFloat(pie.textContent);
        var NS = "http://www.w3.org/2000/svg";
        var svg = document.createElementNS(NS, "svg");
        var circle = document.createElementNS(NS, "circle");
        var title = document.createElementNS(NS, "title");

        circle.setAttribute("r", 16);
        circle.setAttribute("cx", 16);
        circle.setAttribute("cy", 16);
        circle.setAttribute("stroke-dasharray", p + " 100");

        svg.setAttribute("viewBox", "0 0 32 32");
        title.textContent = pie.textContent;
        pie.textContent = '';
        svg.appendChild(title);
        svg.appendChild(circle);
        pie.appendChild(svg);
    });

});

CSS

.pie-wrapper {
    .pie {
        width: 100px;
        height: 100px;
        display: inline-block;
        margin: 10px;
        transform: rotate(-90deg);
    }
    svg {
        background: $primary;
        border-radius: 50%;
    }
    circle {
        fill: $primary;
        stroke: $secondary;
        stroke-width: 32;
    }
    @keyframes grow {
        to {
            stroke-dasharray: 100 100
        }
    }
    .pie.animated {
        animation: grow 2s linear;
    }
}

As you can see I thought I had to simply fiddle with the .pie.animated CSS rules but up to now I've been unable to animate up to my dynamic value, only the full circle.

Basically if my value is 42% I'm trying to grow my circle to 42% of the SVG. But the problem is I can't really give a dynamic value to my CSS animation. Perhaps I might need to use inline CSS but I'm not sure it's possible for animation key frames.

The JSFiddle is here

Upvotes: 0

Views: 1240

Answers (1)

Soley
Soley

Reputation: 1776

I played with your JQuery part of your JSFiddle, and this is what I ended up.

<div class="pie">60%</div>

<div class="pie">90%</div>

<div class="pie">12%</div>

The idea is simple. I use a javascript interval timer to call the count timer every time. I also added some max-val, inc-val and other related variable to make it work.

function $$(selector, context) {
    context = context || document;
    var elements = context.querySelectorAll(selector);
    return Array.prototype.slice.call(elements);
} 

function count(){
    var isUsed = false;
 $$('.pie').forEach(function(pie) {
    var p = parseFloat(pie.textContent);

    if(pie.maxValue == null){
         pie.maxValue = p;
         pie.incValue = p / 100.0;
         pie.lastValue = 0;
    }
    else
        pie.lastValue = pie.lastValue + pie.incValue;

   if(pie.lastValue <= pie.maxValue){
        var NS = "http://www.w3.org/2000/svg";
        var svg = document.createElementNS(NS, "svg");
        var circle = document.createElementNS(NS, "circle");
        var title = document.createElementNS(NS, "title");

        circle.setAttribute("r", 16);
        circle.setAttribute("cx", 16);
        circle.setAttribute("cy", 16);
        circle.setAttribute("stroke-dasharray", pie.lastValue + " 100");

        svg.setAttribute("viewBox", "0 0 32 32");
        title.textContent = pie.textContent;
        pie.textContent = '';
        svg.appendChild(title);
        svg.appendChild(circle);
        pie.appendChild(svg);

       isUsed = true;
   }

});
    if(isUsed)
        window.setTimeout(function() {  count(); }, 30);
}

window.setTimeout(function() {  count(); }, 30);

count();

Upvotes: 2

Related Questions