将填充动画添加到svg饼图

时间:2022-12-03 17:51:34

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.

正如你所看到的,我认为我必须简单地摆弄.pie.animated CSS规则,但到目前为止,我已经无法动画到我的动态值,只有完整的圆圈。

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.

基本上如果我的价值是42%,我试图将我的圈子增加到SVG的42%。但问题是我无法真正为CSS动画赋予动态价值。也许我可能需要使用内联CSS,但我不确定动画关键帧是否可行。

The JSFiddle is here

JSFiddle就在这里

1 个解决方案

#1


2  

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

我玩你的JSFiddle的JQuery部分,这就是我最终的结果。

<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.

这个想法很简单。我每次使用javascript间隔计时器来调用计数计时器。我还添加了一些max-val,inc-val和其他相关变量来使其工作。

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();

#1


2  

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

我玩你的JSFiddle的JQuery部分,这就是我最终的结果。

<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.

这个想法很简单。我每次使用javascript间隔计时器来调用计数计时器。我还添加了一些max-val,inc-val和其他相关变量来使其工作。

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();