将甜甜圈饼图显示为圆形进度Chart.js

9
我想问一下是否有一种方法可以将饼图制作成圆形进度条,并显示百分比值,我只想要一个彩色的片段,类似于这样:

enter image description here

现在这是我的fiddle,我只需要一个数据。

HTML:

<canvas id="chartProgress" width="300px" height="200"></canvas>

JS:

var chartProgress = document.getElementById("chartProgress");
if (chartProgress) {
var myChartCircle = new Chart(chartProgress, {
type: 'doughnut',
data: {
  labels: ["Africa", 'null'],
  datasets: [{
    label: "Population (millions)",
    backgroundColor: ["#5283ff"],
    data: [68, 48]
  }]
},
plugins: [{
  beforeDraw: function(chart) {
    var width = chart.chart.width,
        height = chart.chart.height,
        ctx = chart.chart.ctx;

    ctx.restore();
    var fontSize = (height / 150).toFixed(2);
    ctx.font = fontSize + "em sans-serif";
    ctx.fillStyle = "#9b9b9b";
    ctx.textBaseline = "middle";

    var text = "68%",
        textX = Math.round((width - ctx.measureText(text).width) / 2),
        textY = height / 2;

    ctx.fillText(text, textX, textY);
    ctx.save();
  }
}],
options: {
  legend: {
    display: false,
  },
  responsive: true,
  maintainAspectRatio: false,
  cutoutPercentage: 85
}
});
}

我知道可以使用普通的HTML&CSS或简单插件来完成,但我想使用Chart.js来实现。


脱口而出,你可以通过放置一个虚拟值(例如 68 - 32)来实现所需的效果。但是如果没有一些定制代码或自定义操作,可能很难在中间获取文本。 - Chirag Ravindra
这是一个非常棒的方法。我以前从未想过使用ChartJS来创建圆形进度条。它已经带有动画效果,而且不用担心画布的大小问题,它会被正确地渲染出来。 - Bruno Freire
1个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
13
插件核心API提供不同的钩子,可用于执行自定义代码。您已经使用beforeDraw钩子在甜甜圈中间绘制文本。 现在,您还可以使用beforeInit钩子来修改图表配置,以适应您的需求:
beforeInit: (chart) => {
  const dataset = chart.data.datasets[0];
  chart.data.labels = [dataset.label];
  dataset.data = [dataset.percent, 100 - dataset.percent];
}

考虑到这段代码,您的dataset的定义将如下所示:

{
  label: 'Africa / Population (millions)',
  percent: 68,
  backgroundColor: ['#5283ff']
}

最后,您需要定义一个tooltips.filter,以便工具提示仅出现在相关部分。

tooltips: {
  filter: tooltipItem => tooltipItem.index == 0
}
请看您修订后的代码,查看其运行方式。

var myChartCircle = new Chart('chartProgress', {
  type: 'doughnut',
  data: {
    datasets: [{
      label: 'Africa / Population (millions)',
      percent: 68,
      backgroundColor: ['#5283ff']
    }]
  },
  plugins: [{
      beforeInit: (chart) => {
        const dataset = chart.data.datasets[0];
        chart.data.labels = [dataset.label];
        dataset.data = [dataset.percent, 100 - dataset.percent];
      }
    },
    {
      beforeDraw: (chart) => {
        var width = chart.chart.width,
          height = chart.chart.height,
          ctx = chart.chart.ctx;
        ctx.restore();
        var fontSize = (height / 150).toFixed(2);
        ctx.font = fontSize + "em sans-serif";
        ctx.fillStyle = "#9b9b9b";
        ctx.textBaseline = "middle";
        var text = chart.data.datasets[0].percent + "%",
          textX = Math.round((width - ctx.measureText(text).width) / 2),
          textY = height / 2;
        ctx.fillText(text, textX, textY);
        ctx.save();
      }
    }
  ],
  options: {
    maintainAspectRatio: false,
    cutoutPercentage: 85,
    rotation: Math.PI / 2,
    legend: {
      display: false,
    },
    tooltips: {
      filter: tooltipItem => tooltipItem.index == 0
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="chartProgress"></canvas>


这个答案应该被标记为正确。太棒了! - Bruno Freire

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,