How can I show a subset of data on pie pieces in Chart.JS while still displaying the superset when hovering?

后端 未结 2 1199
猫巷女王i
猫巷女王i 2021-01-16 19:52

I\'ve got a pie chart that looks like this when hovering over a piece of pie:

Except for wanting the legend to the right instead of on top, I\'m fairly cont

相关标签:
2条回答
  • 2021-01-16 20:22

    The following solution is using the same calculation as lamelemon's but using Chart.js plugins, which brings additional benefits :

    • There is no longer this blink effect caused by the animation.onComplete since it occurs immediatly without waiting for antything.

    • The tooltip is above the text, which is more natural.

    Follows the plugin that does it :

    Chart.pluginService.register({
        afterDatasetsDraw: function(chartInstance) {
    
            // We get the canvas context
            var ctx = chartInstance.chart.ctx;
    
            // And set the properties we need
            ctx.font = Chart.helpers.fontString(14, 'bold', Chart.defaults.global.defaultFontFamily);
            ctx.textAlign = 'center';
            ctx.textBaseline = 'bottom';
            ctx.fillStyle = '#666';
    
            // For ervery dataset ...
            chartInstance.config.data.datasets.forEach(function(dataset) {
    
                // For every data in the dataset ...
                for (var i = 0; i < dataset.data.length; i++) {
    
                    // We get all the properties & values we need
                    var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model,
                        total = dataset._meta[Object.keys(dataset._meta)[0]].total,
                        mid_radius = model.innerRadius + (model.outerRadius - model.innerRadius) / 2,
                        start_angle = model.startAngle,
                        end_angle = model.endAngle,
                        mid_angle = start_angle + (end_angle - start_angle) / 2;
    
                    // We calculate the right positions for our text
                    var x = mid_radius * 1.5 * Math.cos(mid_angle);
                    var y = mid_radius * 1.5 * Math.sin(mid_angle);
    
                    // We calculate the percentage
                    var percent = String(Math.round(dataset.data[i] / total * 100)) + "%";
                    // And display it
                    ctx.fillText(percent, model.x + x, model.y + y);
                }
            });
        }
    });
    


    You can check this plugin working on this jsFiddle, and here is the result :

    0 讨论(0)
  • 2021-01-16 20:43

    Alright looks like you have some simple syntax errors in your updated code that probably happened with copying over. Ignoring those, you can manage this by creating a function in your animation options. Here is the fiddle. Thanks to Hung Tran's work here.

    animation: {
      duration: 0,
      easing: "easeOutQuart",
      onComplete: function () {
        var ctx = this.chart.ctx;
        ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontFamily, 'normal', Chart.defaults.global.defaultFontFamily);
        ctx.textAlign = 'center';
        ctx.textBaseline = 'bottom';
    
        this.data.datasets.forEach(function (dataset) {
    
          for (var i = 0; i < dataset.data.length; i++) {
            var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model,
                total = dataset._meta[Object.keys(dataset._meta)[0]].total,
                mid_radius = model.innerRadius + (model.outerRadius - model.innerRadius)/2,
                start_angle = model.startAngle,
                end_angle = model.endAngle,
                mid_angle = start_angle + (end_angle - start_angle)/2;
    
            var x = mid_radius * Math.cos(mid_angle);
            var y = mid_radius * Math.sin(mid_angle);
    
            ctx.fillStyle = '#fff';
            if (i == 3){ // Darker text color for lighter background
              ctx.fillStyle = '#444';
            }
            var percent = String(Math.round(dataset.data[i]/total*100)) + "%";
            // this prints the data number
            ctx.fillText(dataset.data[i], model.x + x, model.y + y);
            // this prints the percentage
            ctx.fillText(percent, model.x + x, model.y + y + 15);
          }
        });               
      }
    }
    
    0 讨论(0)
提交回复
热议问题