Javascript 如何在Chart.JS中显示饼图数据的子集,同时在悬停时仍显示超集?

Javascript 如何在Chart.JS中显示饼图数据的子集,同时在悬停时仍显示超集?,javascript,drawing,chart.js,pie-chart,chart.js2,Javascript,Drawing,Chart.js,Pie Chart,Chart.js2,我有一个饼图,当悬停在一块饼上时,它是这样的: 除了想要图例外,我对此相当满意,但我只想在饼图中显示“始终”的百分比值,并且仍然在悬停时显示(): 换句话说,我希望馅饼看起来像这样: 我如何将这一部分数据(百分比)分解出来,并将其绘制到每个饼图上 以下是我目前使用的代码: var formatter = new Intl.NumberFormat("en-US"); var data = { labels: [ "Bananas (18%)", "Le

我有一个饼图,当悬停在一块饼上时,它是这样的:

除了想要图例外,我对此相当满意,但我只想在饼图中显示“始终”的百分比值,并且仍然在悬停时显示
():

换句话说,我希望馅饼看起来像这样:

我如何将这一部分数据(百分比)分解出来,并将其绘制到每个饼图上

以下是我目前使用的代码:

var formatter = new Intl.NumberFormat("en-US");
var data = {
    labels: [
        "Bananas (18%)",
        "Lettuce, Romaine (14%)",
        "Melons, Watermelon (10%)",
        "Pineapple (10%)",
        "Berries (10%)",
        "Lettuce, Spring Mix (9%)",
        "Broccoli (8%)",
        "Melons, Honeydew (7%)",
        "Grapes (7%)",
        "Melons, Cantaloupe (7%)"
    ],
    datasets: [
        {
            data: [2755, 2256, 1637, 1608, 1603, 1433, 1207, 1076, 1056, 1048],
            backgroundColor: [
                "#FFE135",
                "#3B5323",
                "#fc6c85",
                "#ffec89",
                "#021c3d",
                "#3B5323",
                "#046b00",
                "#cef45a",
                "#421C52",
                "#FEA620"
            ]
        }
    ]
};

var optionsPie = {
    responsive: true,
    scaleBeginAtZero: true,
    tooltips: {
        callbacks: {
            label: function (tooltipItem, data) {
                return data.labels[tooltipItem.index] + ": " +
                    formatter.format(data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index]);
            }
        }
    }
};

var ctx = $("#top10ItemsChart").get(0).getContext("2d");
var top10PieChart = new Chart(ctx,
{
    type: 'pie',
    data: data,
    options: optionsPie
});

$("#top10Legend").html(top10PieChart.generateLegend());
我是否需要添加afterDraw()事件?如果需要,它需要如何完成

更新 我尝试向图表构造函数添加onAnimationComplete()回调:

var top10PieChart = new Chart(ctx,
{
    type: 'pie',
    data: data,
    options: optionsPie,
    onAnimationComplete: function () {
        var ctx = this.chart.ctx;
        ctx.font = this.scale.font;
        ctx.fillStyle = this.scale.textColor;
        ctx.textAlign = "center";
        ctx.textBaseline = "center";

        this.datasets.forEach(function(dataset) {
            dataset.points.forEach(function(points) {
                ctx.fillText(points.value, points.x, points.y - 10);
            });
        });
    }
});
…但它什么也没做

更新2 我还尝试将以下内容附加到options对象:

,
tooltipTemplate: "<%= value %>",
onAnimationComplete: function () {
    this.showTooltip(this.datasets[0].bars, true);
}
在检索对元素的引用后添加:

var midX = canvas.width / 2;
var midY = canvas.height / 2
在构造饼图实例后添加:

var radius = top10PieChart.outerRadius;
添加函数drawSegmentValues()

在上下文中(无意使用双关语):

//十大饼图
var格式化程序=新的国际编号格式(“en-US”);
风险值数据={
标签:[
“香蕉(18%)”,
“生菜、生菜(14%)”,
“西瓜,西瓜(10%)”,
“菠萝(10%)”,
“浆果(10%)”,
“生菜,春季混合(9%)”,
“西兰花(8%)”,
“瓜类、蜜露(7%)”,
“葡萄(7%)”,
瓜类、哈密瓜(7%)
],
数据集:[
{
数据:[27552256163716081603143312071076
1056, 1048],
背景颜色:[
“#FFE135”,
“#3B5323”,
“#fc6c85”,
“#ffec89”,
“#021c3d”,
“#3B5323”,
“#046b00”,
“#cef45a”,
“#421C52”,
“#FEA620”
]
}
]
};
var optionsPie={
回答:是的,
scaleBeginAtZero:对,
图例:{
显示:假
},
工具提示:{
回调:{
标签:函数(工具提示项、数据){
返回数据.标签[tooltipItem.index]+“:”+
格式化程序.format
data.datasets[tooltipItem.datasetIndex].data[
工具提示项索引];
}
}
},
showTooltips:false,
onAnimationProgress:DrawSegmentValue
};
var ctx=$(“#top10itemshart”).get(0.getContext(“2d”);
var midX=canvas.width/2;
var midY=canvas.height/2
var top10PieChart=新图表(ctx,
{
键入“pie”,
数据:数据,
选项:选项饼/,
});
var半径=top10PieChart.outerRadius;
$(“#top10Legend”).html(top10PieChart.generateLegend());

//好吧,看来您的更新代码中有一些简单的语法错误,这些错误可能是在复制过程中发生的。忽略这些,您可以通过在动画选项中创建函数来管理此操作。这是你的电话号码。多亏了洪川的工作

动画:{
持续时间:0,
放松:“放松夸脱”,
onComplete:函数(){
var ctx=this.chart.ctx;
ctx.font=Chart.helpers.fontString(Chart.defaults.global.defaultFontFamily,'normal',Chart.defaults.global.defaultFontFamily);
ctx.textAlign='中心';
ctx.textb基线='底部';
this.data.datasets.forEach(函数(数据集){
对于(var i=0;i
好的,看来您在更新的代码中出现了一些简单的语法错误,这些错误可能是在复制过程中发生的。忽略这些,您可以通过在动画选项中创建函数来管理此操作。这是你的电话号码。多亏了洪川的工作

动画:{
持续时间:0,
放松:“放松夸脱”,
onComplete:函数(){
var ctx=this.chart.ctx;
ctx.font=Chart.helpers.fontString(Chart.defaults.global.defaultFontFamily,'normal',Chart.defaults.global.defaultFontFamily);
ctx.textAlign='中心';
ctx.textb基线='底部';
this.data.datasets.forEach(函数(数据集){
对于(var i=0;ivar radius = top10PieChart.outerRadius;
        // Top 10 Pie Chart
        var formatter = new Intl.NumberFormat("en-US");
        var data = {
            labels: [
                "Bananas (18%)",
                "Lettuce, Romaine (14%)",
                "Melons, Watermelon (10%)",
                "Pineapple (10%)",
                "Berries (10%)",
                "Lettuce, Spring Mix (9%)",
                "Broccoli (8%)",
                "Melons, Honeydew (7%)",
                "Grapes (7%)",
                "Melons, Cantaloupe (7%)"
            ],
            datasets: [
                {
                    data: [2755, 2256, 1637, 1608, 1603, 1433, 1207, 1076
1056, 1048],
                    backgroundColor: [
                        "#FFE135",
                        "#3B5323",
                        "#fc6c85",
                        "#ffec89",
                        "#021c3d",
                        "#3B5323",
                        "#046b00",
                        "#cef45a",
                        "#421C52",
                        "#FEA620"
                    ]
                }
            ]
        };

        var optionsPie = {
            responsive: true,
            scaleBeginAtZero: true,
            legend: {
                display: false
            },
            tooltips: {
                callbacks: {
                    label: function (tooltipItem, data) {
                        return data.labels[tooltipItem.index] + ": " +
                         formatter.format
data.datasets[tooltipItem.datasetIndex].data[
tooltipItem.index]);
                    }
                }
            },
            showTooltips: false,
            onAnimationProgress: drawSegmentValues
        };

        var ctx = $("#top10ItemsChart").get(0).getContext("2d");
        var midX = canvas.width / 2;
        var midY = canvas.height / 2
        var top10PieChart = new Chart(ctx,
        {
            type: 'pie',
            data: data,
            options: optionsPie//,
        });
        var radius = top10PieChart.outerRadius;

        $("#top10Legend").html(top10PieChart.generateLegend());
        // </ Top 10 Pie Chart

        // Price Compliance Bar Chart
        . . . this horizontal bar chart code elided for brevity, bu
unchanged from their working state
        // Forecast/Impact Analysis Bar chart
        . . . this horizontal bar chart code also elided for brevity, bu
unchanged from their working state

    function drawSegmentValues() {
        for (var i = 0; i < top10PieChart.segments.length; i++) {
            ctx.fillStyle = "white";
            var textSize = canvas.width / 10;
            ctx.font = textSize + "px Verdana";
            // Get needed variables
            var value = top10PieChart.segments[i].value;
            var startAngle = top10PieChart.segments[i].startAngle;
            var endAngle = top10PieChart.segments[i].endAngle;
            var middleAngle = startAngle + ((endAngle - startAngle)
2);

            // Compute text location
            var posX = (radius / 2) * Math.cos(middleAngle) + midX;
            var posY = (radius / 2) * Math.sin(middleAngle) + midY;

            // Text offside by middle
            var w_offset = ctx.measureText(value).width / 2;
            var h_offset = textSize / 4;

            ctx.fillText(value, posX - w_offset, posY + h_offset);
        }
    }
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);
      }
    });               
  }
}