0

I am currently trying to add a counter animation to the values presented once you click on a specific slice of the donut chart I have created, the counter will count up to the data values attached to that specific slice, however the animation is awfully slow for larger numbers as seen with the middle data.

I want to know how I can speed up the animation, and additionally how I would be able to show the value as a double with decimals, right now when you hover the slices of the chart, the tooltip shows the correct value, e.g 1399,99, however the counter in the centre of the chart will count to 1400 instead.

$(function() {
  // Create the chart
  addLabel = function(point) {
    $('.cLabel').remove();
    var i = 0,
      text = '<span style="color: #323232; font-size: 14px;">' + point.name + '</span><br/>' + '<span style="font-size: 16px; color: #323232;">kr ' +  point.subtotal + ' / måned</span><br/>' + '<span style="font-size: 14px; color: #323232;">' + point.y + '</span><br/>',
      chart = point.series.chart,
      renderer = chart.renderer;
    chart.renderer.label(text, chart.chartWidth / 2.02, chart.chartHeight / 2.14).attr({
      'text-anchor': 'middle',
    }).addClass('cLabel').add();
    var intervalsubtotal = setInterval(function() {
      if (i < point.subtotal) {
        i++;
        $('.cLabel')[0].lastChild.lastChild.previousSibling.innerHTML = 'kr ' + i + ' / måned';
      } else {
        clearInterval(interval);
      }
    }, 10 / point.subtotal)
    var j = 0;
    var intervalusers = setInterval(function() {
      if (j < point.y) {
        j++;
        $('.cLabel')[0].lastChild.lastChild.innerHTML = 'Antal brugere: ' + j;
      } else {
        clearInterval(interval);
      }
    }, 500 / point.y
    )};
  • Animation is too slow
  • Does not show values with decimals (double)
  • Whenever you click another value the counter starts to glitch if its already counting (may be fixed with increased animation speed)

jsFiddle

Madvillain
  • 86
  • 1
  • 9
  • Well, to start with the animation, I would recommend to use a jQuery function with different easing styles. This will also solve your third issue as you can stop those animations before starting a new one. Some examples: http://stackoverflow.com/questions/2540277/jquery-counter-to-count-up-to-a-target-number – nilsole Oct 06 '16 at 12:01
  • http://stackoverflow.com/a/24683499/2381339 – nilsole Oct 06 '16 at 12:07
  • Thanks for your reply, I thought so too, however I am not quite sure how to implement it properly – Madvillain Oct 06 '16 at 12:09
  • 1
    Similar topic: http://stackoverflow.com/questions/39768421/onclick-display-donut-chart-pieces-information-in-center/39769016?noredirect=1#comment67067497_39769016 – Grzegorz Blachliński Oct 06 '16 at 17:52

2 Answers2

1

Please check my comments below, it may help you

  1. Animation is too slow

    • Use duration option in chart - animation like below

      chart:{
             animation: { duration: 10 }
            }
      
  2. Does not show values with decimals (double)

    • replace j with point.y as j is an integer value.
  3. Whenever you click another value the counter starts to glitch if its already counting (may be fixed with increased animation speed)

    • animation speed can be increased by decreasing duration amount.

Please check below snippet.

$(function() {
  // Create the chart
  addLabel = function(point) {
  var interval = 0;
  var i = 0;
    $('.cLabel').remove();
    
      text = '<span style="color: #323232; font-size: 14px;">' + point.name + '</span><br/>'+ '<span style="font-size: 16px; color: #323232;">kr ' +  point.subtotal + ' / måned</span><br/>' + '<span style="font-size: 14px; color: #323232;">' + point.y + '</span><br/>' ,
      chart = point.series.chart,
      renderer = chart.renderer;
    chart.renderer.label(text, chart.chartWidth / 2.02, chart.chartHeight / 2.14).attr({
      'text-anchor': 'middle',
    }).addClass('cLabel').add();
    var intervalsubtotal = setInterval(function() {
      if (i < point.subtotal) {
        i++;
        $('.cLabel')[0].lastChild.lastChild.previousSibling.innerHTML = 'kr ' + i + ' / måned';
      } else {
        clearInterval(interval);
      }
    }, 10 / point.subtotal)
    var j = 0;
    var intervalusers = setInterval(function() {
      if (j < point.y) {
        $('.cLabel')[0].lastChild.lastChild.innerHTML = 'Antal brugere: ' + j.toFixed(1);
        j= j+0.1;
      } else {
        clearInterval(interval);
      }
    }, 500 / point.y
    )};
  chart = new Highcharts.Chart({
    chart: {
     animation: {
            duration: 10
        },
      renderTo: 'container',
      type: 'pie',
      events: {
        redraw: function() {
          var chart = this;
          $('.cLabel').attr({
            transform: 'translate(' + chart.chartWidth / 2 + ',' + chart.chartHeight / 2 + ')'
          })
        }
      }
    },
    title: {
      text: 'User diversity and their subtotals'
    },
    yAxis: {
      title: {
        text: 'User diversity and their subtotals'
      }
    },
    plotOptions: {
      pie: {
        allowPointSelect: true,
        cursor: 'pointer',
        shadow: false,
        borderColor: "#000000",
        borderWidth: 0.6
      },
      series: {
        point: {
          events: {
            click: function() {
              addLabel(this);
            }
          }
        }
      }
    },
    tooltip: {
      formatter: function() {
        return '<b>' + this.point.name + '</b>: ' + this.y + '<br>' + '<b>' + 'Subtotal: ' + '</b>' + this.point.subtotal + ' kr';
      }
    },
    series: [{
      data: [{
        name: 'Administrative Brugere',
        y: 4,
        subtotal: 7899.99,
        color: "#B83D5A"
      }, {
        name: 'Begrænsede Brugere',
        y: 8,
        subtotal: 5799.99,
        color: "#9B344C"
      }, {
        name: 'Resource Bruger',
        y: 14,
        subtotal: 2399.99,
        color: "#7A293C"
      }, {
        name: 'Ressource',
        y: 18.1,
        subtotal: 1299.89,
        color: "#5C1F2D"
      }],
      size: '80%',
      innerSize: '82%',
      showInLegend: false,
      dataLabels: {
        enabled: false
      }
    }]
  });
});
@import "bourbon";

@import url(//fonts.googleapis.com/css?family=Oswald:400);
body {
  font-family: "Oswald", sans-serif;
  color: #545454;
}

.cLabel {
    font-family: "Oswald", sans-serif;
    font-color: #545454;
    line-height: 15px;
}

#container {
  background: linear-gradient(#ffffff, #e0dfdf);
}

.stats {
  width: 160px;
  height: 90px!important;
  display: inline-block;
  z-index: 10;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>

<div id="container" style="min-width: 400px; height: 400px; margin: 0 auto;"></div>
<span id="displayStats" class="stats"></span>
B. Dave
  • 81
  • 3
  • Thanks for your answer, how can duration amount be decreased? Also note that when you changed `j` to `point.y` the count up animation stopped working for that data display, when I was talking about animation being too slow I meant for the counter counting up the values when a slice is clicked, not the chart itself. – Madvillain Oct 06 '16 at 12:17
  • Oh okay! Sorry for misinterpretation. I have edited my answer for decimal value. Use `j= j+0.1` and `j.toFixed(2)` For duration, I think you got your answer from nilsole. – B. Dave Oct 06 '16 at 12:37
  • No worries, thanks for taking your time to read and respond to my question. – Madvillain Oct 06 '16 at 12:41
1

Here is my solution, also find this on jsfiddle. The options globalDurationMilliseconds and globalEasing are mandatory, read more about that here: http://api.jquery.com/animate/

    $(function() {
    var globalDurationMilliseconds = 500,
        globalEasing = 'linear';
    // Create the chart
    addLabel = function(point) {
        $('.cLabel').remove();
        var i = 0,
            text = '<span style="color: #323232; font-size: 14px;">' + point.name + '</span><br/>' + '<span style="font-size: 16px; color: #323232;">kr ' + point.subtotal + ' / måned</span><br/>' + '<span style="font-size: 14px; color: #323232;">' + point.y + '</span><br/>',
            chart = point.series.chart,
            renderer = chart.renderer;
        chart.renderer.label(text, chart.chartWidth / 2.02, chart.chartHeight / 2.14).attr({
            'text-anchor': 'middle',
        }).addClass('cLabel').add();

        $({
            numberValue: 0
        }).animate({
            numberValue: point.subtotal
        }, {
            duration: globalDurationMilliseconds,
            easing: globalEasing,
            progress: function() {
                $($('.cLabel')[0].lastChild.lastChild.previousSibling).text((Math.ceil(this.numberValue * 1000) / 1000) + ' / måned');
            }
        });

        $({
            numberValue: 0
        }).animate({
            numberValue: point.y
        }, {
            duration: globalDurationMilliseconds,
            easing: globalEasing,
            progress: function() {
                $($('.cLabel')[0].lastChild.lastChild).text('Antal brugere: ' + Math.ceil(this.numberValue));
            }
        });


    };
    chart = new Highcharts.Chart({
        chart: {
            renderTo: 'container',
            type: 'pie',
            events: {
                redraw: function() {
                    var chart = this;
                    $('.cLabel').attr({
                        transform: 'translate(' + chart.chartWidth / 2 + ',' + chart.chartHeight / 2 + ')'
                    })
                }
            }
        },
        title: {
            text: 'User diversity and their subtotals'
        },
        yAxis: {
            title: {
                text: 'User diversity and their subtotals'
            }
        },
        plotOptions: {
            pie: {
                allowPointSelect: true,
                cursor: 'pointer',
                shadow: false,
                borderColor: "#000000",
                borderWidth: 0.6
            },
            series: {
                point: {
                    events: {
                        click: function() {
                            addLabel(this)
                        }
                    }
                }
            }
        },
        tooltip: {
            formatter: function() {
                return '<b>' + this.point.name + '</b>: ' + this.y + '<br>' + '<b>' + 'Subtotal: ' + '</b>' + this.point.subtotal + ' kr';
            }
        },
        series: [{
            data: [{
                name: 'Administrative Brugere',
                y: 4,
                subtotal: 7899.99,
                color: "#B83D5A"
            }, {
                name: 'Begrænsede Brugere',
                y: 8,
                subtotal: 5799.99,
                color: "#9B344C"
            }, {
                name: 'Resource Bruger',
                y: 14,
                subtotal: 2399.99,
                color: "#7A293C"
            }, {
                name: 'Ressource',
                y: 18,
                subtotal: 1299.89,
                color: "#5C1F2D"
            }],
            size: '80%',
            innerSize: '82%',
            showInLegend: false,
            dataLabels: {
                enabled: false
            }
        }]
    });
});
nilsole
  • 1,663
  • 2
  • 12
  • 28
  • Thanks for the response, did you test your solution? when I enter the code, none of the animations work the data is just being displayed. – Madvillain Oct 06 '16 at 12:24
  • Ah just as you wrote your reply I got your example working, thanks a bunch that's exactly what I needed, you're a champ. – Madvillain Oct 06 '16 at 12:26